diff --git a/tests/intense/block_tests.cpp b/tests/intense/block_tests.cpp index f6bca83e..f603fb74 100644 --- a/tests/intense/block_tests.cpp +++ b/tests/intense/block_tests.cpp @@ -16,6 +16,7 @@ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include #include #include @@ -236,4 +237,77 @@ BOOST_FIXTURE_TEST_CASE( update_account_keys, database_fixture ) } } +/** + * To have a secure random number we need to ensure that the same + * delegate does not get to produce two blocks in a row. There is + * always a chance that the last delegate of one round will be the + * first delegate of the next round. + * + * This means that when we shuffle delegates we need to make sure + * that there is at least N/2 delegates between consecutive turns + * of the same delegate. This means that durring the random + * shuffle we need to restrict the placement of delegates to maintain + * this invariant. + * + * This test checks the requirement using Monte Carlo approach + * (produce lots of blocks and check the invariant holds). + */ +BOOST_FIXTURE_TEST_CASE( delegate_groups_mc_test, database_fixture ) +{ + try { + size_t num_witnesses = db.get_global_properties().active_witnesses.size(); + size_t dmin = num_witnesses >> 1; + + vector< witness_id_type > cur_round; + vector< witness_id_type > full_schedule; + // if we make the maximum witness count testable, + // we'll need to enlarge this. + std::bitset< 0x40 > witness_seen; + size_t total_blocks = 1000000; + + cur_round.reserve( num_witnesses ); + full_schedule.reserve( total_blocks ); + + // we assert so the test doesn't continue, which would + // corrupt memory + assert( num_witnesses <= witness_seen.size() ); + + while( full_schedule.size() < total_blocks ) + { + witness_id_type wid = db.get_scheduled_witness( 1 ).first; + full_schedule.push_back( wid ); + cur_round.push_back( wid ); + if( cur_round.size() == num_witnesses ) + { + wdump( (cur_round) ); + // check that the current round contains exactly 1 copy + // of each witness + witness_seen.reset(); + for( const witness_id_type& w : cur_round ) + { + uint64_t inst = w.instance.value; + BOOST_CHECK( !witness_seen.test( inst ) ); + assert( !witness_seen.test( inst ) ); + witness_seen.set( inst ); + } + cur_round.clear(); + } + generate_block(); + } + + for( size_t i=0,m=full_schedule.size(); iaccumulated_income.value, 0); } FC_LOG_AND_RETHROW() } -/** - * To have a secure random number we need to ensure that the same - * delegate does not get to produce two blocks in a row. There is - * always a chance that the last delegate of one round will be the - * first delegate of the next round. - * - * This means that when we shuffle delegates we need to make sure - * that there is at least N/2 delegates between consecutive turns - * of the same delegate. This means that durring the random - * shuffle we need to restrict the placement of delegates to maintain - * this invariant. - */ -BOOST_AUTO_TEST_CASE_EXPECTED_FAILURES( unimp_delegate_groups_test, 1 ) -BOOST_AUTO_TEST_CASE( unimp_delegate_groups_test ) -{ - BOOST_FAIL( "not implemented" ); -} - - /** * This test should simulate a prediction market which means the following: *