Changeset View
Changeset View
Standalone View
Standalone View
src/test/avalanche_tests.cpp
Show All 25 Lines | |||||
#define REGISTER_VOTE_AND_CHECK(vr, vote, state, finalized, confidence) \ | #define REGISTER_VOTE_AND_CHECK(vr, vote, state, finalized, confidence) \ | ||||
vr.registerVote(vote); \ | vr.registerVote(vote); \ | ||||
BOOST_CHECK_EQUAL(vr.isAccepted(), state); \ | BOOST_CHECK_EQUAL(vr.isAccepted(), state); \ | ||||
BOOST_CHECK_EQUAL(vr.hasFinalized(), finalized); \ | BOOST_CHECK_EQUAL(vr.hasFinalized(), finalized); \ | ||||
BOOST_CHECK_EQUAL(vr.getConfidence(), confidence); | BOOST_CHECK_EQUAL(vr.getConfidence(), confidence); | ||||
BOOST_AUTO_TEST_CASE(vote_record) { | BOOST_AUTO_TEST_CASE(vote_record) { | ||||
VoteRecord vr; | VoteRecord vraccepted(true); | ||||
// Check initial state. | |||||
BOOST_CHECK_EQUAL(vraccepted.isAccepted(), true); | |||||
BOOST_CHECK_EQUAL(vraccepted.hasFinalized(), false); | |||||
BOOST_CHECK_EQUAL(vraccepted.getConfidence(), 0); | |||||
VoteRecord vr(false); | |||||
// Check initial state. | // Check initial state. | ||||
BOOST_CHECK_EQUAL(vr.isAccepted(), false); | BOOST_CHECK_EQUAL(vr.isAccepted(), false); | ||||
BOOST_CHECK_EQUAL(vr.hasFinalized(), false); | BOOST_CHECK_EQUAL(vr.hasFinalized(), false); | ||||
BOOST_CHECK_EQUAL(vr.getConfidence(), 0); | BOOST_CHECK_EQUAL(vr.getConfidence(), 0); | ||||
// We register one vote for, which keep things at 4/4. | // We register one vote for, which keep things at 4/4. | ||||
REGISTER_VOTE_AND_CHECK(vr, true, false, false, 0); | REGISTER_VOTE_AND_CHECK(vr, true, false, false, 0); | ||||
▲ Show 20 Lines • Show All 100 Lines • ▼ Show 20 Lines | BOOST_AUTO_TEST_CASE(block_register) { | ||||
// Add a new block. Check it is added to the polls. | // Add a new block. Check it is added to the polls. | ||||
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); | ||||
BOOST_CHECK_EQUAL(invs[0].type, MSG_BLOCK); | BOOST_CHECK_EQUAL(invs[0].type, MSG_BLOCK); | ||||
BOOST_CHECK(invs[0].hash == blockHash); | BOOST_CHECK(invs[0].hash == blockHash); | ||||
// Newly added blocks are also considered rejected. | // Newly added blocks' state reflect the blockchain. | ||||
BOOST_CHECK(!p.isAccepted(pindex)); | BOOST_CHECK(p.isAccepted(pindex)); | ||||
// Let's vote for this block a few times. | // Let's vote for this block a few times. | ||||
AvalancheResponse resp{0, {AvalancheVote(0, blockHash)}}; | AvalancheResponse resp{0, {AvalancheVote(0, blockHash)}}; | ||||
for (int i = 0; i < 5; i++) { | for (int i = 0; i < 4; i++) { | ||||
AvalancheTest::runEventLoop(p); | AvalancheTest::runEventLoop(p); | ||||
BOOST_CHECK(p.registerVotes(nodeid, resp, updates)); | BOOST_CHECK(p.registerVotes(nodeid, resp, updates)); | ||||
BOOST_CHECK(!p.isAccepted(pindex)); | BOOST_CHECK(p.isAccepted(pindex)); | ||||
BOOST_CHECK_EQUAL(updates.size(), 0); | BOOST_CHECK_EQUAL(updates.size(), 0); | ||||
} | } | ||||
// Now the state will flip. | // We vote for it numerous times to finalize it. | ||||
AvalancheTest::runEventLoop(p); | for (int i = 0; i < AVALANCHE_FINALIZATION_SCORE; i++) { | ||||
BOOST_CHECK(p.registerVotes(nodeid, resp, updates)); | |||||
BOOST_CHECK(p.isAccepted(pindex)); | |||||
BOOST_CHECK_EQUAL(updates.size(), 1); | |||||
BOOST_CHECK(updates[0].getBlockIndex() == pindex); | |||||
BOOST_CHECK_EQUAL(updates[0].getStatus(), | |||||
AvalancheBlockUpdate::Status::Accepted); | |||||
updates = {}; | |||||
// Now it is accepted, but we can vote for it numerous times. | |||||
for (int i = 1; i < AVALANCHE_FINALIZATION_SCORE; i++) { | |||||
AvalancheTest::runEventLoop(p); | AvalancheTest::runEventLoop(p); | ||||
BOOST_CHECK(p.registerVotes(nodeid, resp, updates)); | BOOST_CHECK(p.registerVotes(nodeid, resp, updates)); | ||||
BOOST_CHECK(p.isAccepted(pindex)); | BOOST_CHECK(p.isAccepted(pindex)); | ||||
BOOST_CHECK_EQUAL(updates.size(), 0); | BOOST_CHECK_EQUAL(updates.size(), 0); | ||||
} | } | ||||
// As long as it is not finalized, we poll. | // As long as it is not finalized, we poll. | ||||
invs = AvalancheTest::getInvsForNextPoll(p); | invs = AvalancheTest::getInvsForNextPoll(p); | ||||
Show All 16 Lines | BOOST_AUTO_TEST_CASE(block_register) { | ||||
// Now let's undo this and finalize rejection. | // Now let's undo this and finalize rejection. | ||||
BOOST_CHECK(p.addBlockToReconcile(pindex)); | BOOST_CHECK(p.addBlockToReconcile(pindex)); | ||||
invs = AvalancheTest::getInvsForNextPoll(p); | invs = AvalancheTest::getInvsForNextPoll(p); | ||||
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, MSG_BLOCK); | ||||
BOOST_CHECK(invs[0].hash == blockHash); | BOOST_CHECK(invs[0].hash == blockHash); | ||||
// Only 3 here as we don't need to flip state. | |||||
resp = {0, {AvalancheVote(1, blockHash)}}; | resp = {0, {AvalancheVote(1, blockHash)}}; | ||||
for (int i = 0; i < 3; i++) { | for (int i = 0; i < 4; i++) { | ||||
AvalancheTest::runEventLoop(p); | AvalancheTest::runEventLoop(p); | ||||
BOOST_CHECK(p.registerVotes(nodeid, resp, updates)); | BOOST_CHECK(p.registerVotes(nodeid, resp, updates)); | ||||
BOOST_CHECK(!p.isAccepted(pindex)); | BOOST_CHECK(p.isAccepted(pindex)); | ||||
BOOST_CHECK_EQUAL(updates.size(), 0); | BOOST_CHECK_EQUAL(updates.size(), 0); | ||||
} | } | ||||
// Now the state will flip. | |||||
AvalancheTest::runEventLoop(p); | |||||
BOOST_CHECK(p.registerVotes(nodeid, resp, updates)); | |||||
BOOST_CHECK(!p.isAccepted(pindex)); | |||||
BOOST_CHECK_EQUAL(updates.size(), 1); | |||||
BOOST_CHECK(updates[0].getBlockIndex() == pindex); | |||||
BOOST_CHECK_EQUAL(updates[0].getStatus(), | |||||
AvalancheBlockUpdate::Status::Rejected); | |||||
updates = {}; | |||||
// Now it is rejected, but we can vote for it numerous times. | // Now it is rejected, but we can vote for it numerous times. | ||||
for (int i = 0; i < AVALANCHE_FINALIZATION_SCORE; i++) { | for (int i = 1; i < AVALANCHE_FINALIZATION_SCORE; i++) { | ||||
AvalancheTest::runEventLoop(p); | AvalancheTest::runEventLoop(p); | ||||
BOOST_CHECK(p.registerVotes(nodeid, resp, updates)); | BOOST_CHECK(p.registerVotes(nodeid, resp, updates)); | ||||
BOOST_CHECK(!p.isAccepted(pindex)); | BOOST_CHECK(!p.isAccepted(pindex)); | ||||
BOOST_CHECK_EQUAL(updates.size(), 0); | BOOST_CHECK_EQUAL(updates.size(), 0); | ||||
} | } | ||||
// As long as it is not finalized, we poll. | // As long as it is not finalized, we poll. | ||||
invs = AvalancheTest::getInvsForNextPoll(p); | invs = AvalancheTest::getInvsForNextPoll(p); | ||||
Show All 13 Lines | BOOST_AUTO_TEST_CASE(block_register) { | ||||
// Once the decision is finalized, there is no poll for it. | // Once the decision is finalized, there is no poll for it. | ||||
invs = AvalancheTest::getInvsForNextPoll(p); | invs = AvalancheTest::getInvsForNextPoll(p); | ||||
BOOST_CHECK_EQUAL(invs.size(), 0); | BOOST_CHECK_EQUAL(invs.size(), 0); | ||||
// Adding the block twice does nothing. | // Adding the block twice does nothing. | ||||
BOOST_CHECK(p.addBlockToReconcile(pindex)); | BOOST_CHECK(p.addBlockToReconcile(pindex)); | ||||
BOOST_CHECK(!p.addBlockToReconcile(pindex)); | BOOST_CHECK(!p.addBlockToReconcile(pindex)); | ||||
BOOST_CHECK(!p.isAccepted(pindex)); | BOOST_CHECK(p.isAccepted(pindex)); | ||||
CConnmanTest::ClearNodes(); | CConnmanTest::ClearNodes(); | ||||
} | } | ||||
BOOST_AUTO_TEST_CASE(multi_block_register) { | BOOST_AUTO_TEST_CASE(multi_block_register) { | ||||
AvalancheProcessor p(g_connman.get()); | AvalancheProcessor p(g_connman.get()); | ||||
CBlockIndex indexA, indexB; | CBlockIndex indexA, indexB; | ||||
Show All 39 Lines | BOOST_AUTO_TEST_CASE(multi_block_register) { | ||||
// 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, MSG_BLOCK); | ||||
BOOST_CHECK(invs[0].hash == blockHashB); | BOOST_CHECK(invs[0].hash == blockHashB); | ||||
BOOST_CHECK_EQUAL(invs[1].type, MSG_BLOCK); | BOOST_CHECK_EQUAL(invs[1].type, MSG_BLOCK); | ||||
BOOST_CHECK(invs[1].hash == blockHashA); | BOOST_CHECK(invs[1].hash == blockHashA); | ||||
// Let's vote for these blocks a few times. | // Let's vote for these blocks a few times. | ||||
for (int i = 0; i < 4; i++) { | for (int i = 0; i < 3; i++) { | ||||
AvalancheTest::runEventLoop(p); | AvalancheTest::runEventLoop(p); | ||||
BOOST_CHECK(p.registerVotes(node0->GetId(), resp, updates)); | BOOST_CHECK(p.registerVotes(node0->GetId(), resp, updates)); | ||||
BOOST_CHECK_EQUAL(updates.size(), 0); | BOOST_CHECK_EQUAL(updates.size(), 0); | ||||
} | } | ||||
// Now the state will flip for A. | // Now it is accepted, but we can vote for it numerous times. | ||||
AvalancheTest::runEventLoop(p); | for (int i = 0; i < AVALANCHE_FINALIZATION_SCORE; i++) { | ||||
BOOST_CHECK(p.registerVotes(node0->GetId(), resp, updates)); | |||||
BOOST_CHECK_EQUAL(updates.size(), 1); | |||||
BOOST_CHECK(updates[0].getBlockIndex() == pindexA); | |||||
BOOST_CHECK_EQUAL(updates[0].getStatus(), | |||||
AvalancheBlockUpdate::Status::Accepted); | |||||
updates = {}; | |||||
// And then for B. | |||||
AvalancheTest::runEventLoop(p); | |||||
BOOST_CHECK(p.registerVotes(node0->GetId(), resp, updates)); | |||||
BOOST_CHECK_EQUAL(updates.size(), 1); | |||||
BOOST_CHECK(updates[0].getBlockIndex() == pindexB); | |||||
BOOST_CHECK_EQUAL(updates[0].getStatus(), | |||||
AvalancheBlockUpdate::Status::Accepted); | |||||
updates = {}; | |||||
// Now it is rejected, but we can vote for it numerous times. | |||||
for (int i = 2; i < AVALANCHE_FINALIZATION_SCORE; i++) { | |||||
AvalancheTest::runEventLoop(p); | AvalancheTest::runEventLoop(p); | ||||
BOOST_CHECK(p.registerVotes(node0->GetId(), resp, updates)); | BOOST_CHECK(p.registerVotes(node0->GetId(), resp, updates)); | ||||
BOOST_CHECK_EQUAL(updates.size(), 0); | BOOST_CHECK_EQUAL(updates.size(), 0); | ||||
} | } | ||||
// Running two iterration of the event loop so that vote gets triggerd on A | // Running two iterration of the event loop so that vote gets triggerd on A | ||||
// and B. | // and B. | ||||
AvalancheTest::runEventLoop(p); | AvalancheTest::runEventLoop(p); | ||||
▲ Show 20 Lines • Show All 111 Lines • ▼ Show 20 Lines | BOOST_AUTO_TEST_CASE(poll_and_response) { | ||||
// Making request for invalid nodes do not work. | // Making request for invalid nodes do not work. | ||||
BOOST_CHECK(!p.registerVotes(avanodeid + 1234, resp, updates)); | BOOST_CHECK(!p.registerVotes(avanodeid + 1234, resp, updates)); | ||||
BOOST_CHECK_EQUAL(updates.size(), 0); | BOOST_CHECK_EQUAL(updates.size(), 0); | ||||
// Out of order response are rejected. | // Out of order response are rejected. | ||||
CBlock block2 = CreateAndProcessBlock({}, CScript()); | CBlock block2 = CreateAndProcessBlock({}, CScript()); | ||||
const uint256 blockHash2 = block2.GetHash(); | const uint256 blockHash2 = block2.GetHash(); | ||||
const CBlockIndex *pindex2 = mapBlockIndex[blockHash2]; | CBlockIndex *pindex2 = mapBlockIndex[blockHash2]; | ||||
BOOST_CHECK(p.addBlockToReconcile(pindex2)); | BOOST_CHECK(p.addBlockToReconcile(pindex2)); | ||||
resp = {0, {AvalancheVote(0, blockHash), AvalancheVote(0, blockHash2)}}; | resp = {0, {AvalancheVote(0, blockHash), AvalancheVote(0, blockHash2)}}; | ||||
AvalancheTest::runEventLoop(p); | AvalancheTest::runEventLoop(p); | ||||
BOOST_CHECK(!p.registerVotes(avanodeid, resp, updates)); | BOOST_CHECK(!p.registerVotes(avanodeid, resp, updates)); | ||||
BOOST_CHECK_EQUAL(updates.size(), 0); | BOOST_CHECK_EQUAL(updates.size(), 0); | ||||
BOOST_CHECK_EQUAL(AvalancheTest::getSuitableNodeToQuery(p), avanodeid); | BOOST_CHECK_EQUAL(AvalancheTest::getSuitableNodeToQuery(p), avanodeid); | ||||
// When a block is marked invalid, stop polling. | |||||
pindex2->nStatus = pindex2->nStatus.withFailed(); | |||||
resp = {0, {AvalancheVote(0, blockHash)}}; | |||||
AvalancheTest::runEventLoop(p); | |||||
BOOST_CHECK(p.registerVotes(avanodeid, resp, updates)); | |||||
BOOST_CHECK_EQUAL(updates.size(), 0); | |||||
BOOST_CHECK_EQUAL(AvalancheTest::getSuitableNodeToQuery(p), avanodeid); | |||||
CConnmanTest::ClearNodes(); | CConnmanTest::ClearNodes(); | ||||
} | } | ||||
BOOST_AUTO_TEST_CASE(event_loop) { | BOOST_AUTO_TEST_CASE(event_loop) { | ||||
AvalancheProcessor p(g_connman.get()); | AvalancheProcessor p(g_connman.get()); | ||||
CScheduler s; | CScheduler s; | ||||
CBlock block = CreateAndProcessBlock({}, CScript()); | CBlock block = CreateAndProcessBlock({}, CScript()); | ||||
▲ Show 20 Lines • Show All 80 Lines • Show Last 20 Lines |