diff --git a/src/test/chain_tests.cpp b/src/test/chain_tests.cpp index d2d68289e73..daae8f3f989 100644 --- a/src/test/chain_tests.cpp +++ b/src/test/chain_tests.cpp @@ -7,6 +7,7 @@ #include #include +#include #include BOOST_FIXTURE_TEST_SUITE(chain_tests, BasicTestingSetup) @@ -85,6 +86,64 @@ BOOST_AUTO_TEST_CASE(basic_tests) BOOST_CHECK_EQUAL(chain_0.Genesis(), nullptr); } +BOOST_AUTO_TEST_CASE(findfork_tests) +{ + // Create a forking chain + const auto init_branch{[](auto& blocks, CBlockIndex* parent, int start_height) { + for (size_t i{0}; i < blocks.size(); ++i) { + blocks[i].pprev = i == 0 ? parent : &blocks[i - 1]; + blocks[i].nHeight = start_height + i; + } + }}; + + const auto check_same{[](const CChain& chain, const auto& blocks) { + for (const auto& block : blocks) { + BOOST_CHECK_EQUAL(chain.FindFork(&block), &block); + } + }}; + + const auto check_fork_point{[](const CChain& chain, const auto& blocks, const CBlockIndex& fork_point) { + for (const auto& block : blocks) { + BOOST_CHECK_EQUAL(chain.FindFork(&block), &fork_point); + } + }}; + + std::array blocks_common; + init_branch(blocks_common, nullptr, 0); + + std::array blocks_long; + init_branch(blocks_long, &blocks_common.back(), blocks_common.size()); + + std::array blocks_short; + init_branch(blocks_short, &blocks_common.back(), blocks_common.size()); + + // Create a chain with the longer fork + CChain chain_long; + chain_long.SetTip(blocks_long.back()); + BOOST_CHECK_EQUAL(chain_long.Height(), 10 + 10 - 1); + // Test the blocks in the common part -> result should be the same + check_same(chain_long, blocks_common); + // Test the blocks on the longer fork -> result should be the same + check_same(chain_long, blocks_long); + // Test the blocks on the other shorter fork -> result should be the fork point + check_fork_point(chain_long, blocks_short, blocks_common.back()); + + // Create a chain with the shorter fork + CChain chain_short; + chain_short.SetTip(blocks_short.back()); + BOOST_CHECK_EQUAL(chain_short.Height(), 10 + 5 - 1); + // Test the blocks in the common part -> result should be the same + check_same(chain_short, blocks_common); + // Test the blocks on the shorter fork -> result should be the same + check_same(chain_short, blocks_short); + // Test the blocks on the other longer fork -> result should be the fork point + check_fork_point(chain_short, blocks_long, blocks_common.back()); + + // Invalid test case. Mixing chains is not supported + CBlockIndex block_on_unrelated_chain; + BOOST_CHECK_EQUAL(chain_long.FindFork(&block_on_unrelated_chain), nullptr); +} + BOOST_AUTO_TEST_CASE(chain_test) { FastRandomContext ctx;