Skip to content

Commit

Permalink
Merge pull request #807 from AntelopeIO/gh_764
Browse files Browse the repository at this point in the history
Add new unittest to validate current finalizer safety file i/o
  • Loading branch information
greg7mdp authored Sep 20, 2024
2 parents 07e3e79 + 55c7136 commit dfc2516
Show file tree
Hide file tree
Showing 3 changed files with 108 additions and 44 deletions.
2 changes: 1 addition & 1 deletion libraries/testing/tester.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -375,7 +375,7 @@ namespace eosio::testing {
// only block number is signaled, in forking tests will get the same block number more than once.
});
[[maybe_unused]] auto accepted_block_header_connection = control->accepted_block_header().connect([this](const block_signal_params& t) {
const auto& [block, id] = t;
[[maybe_unused]] const auto& [block, id] = t;
assert(block);
assert(_check_signal(id, block_signal::accepted_block_header));
});
Expand Down
46 changes: 23 additions & 23 deletions plugins/producer_plugin/test/test_block_timing_util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ BOOST_AUTO_TEST_CASE(test_calculate_producer_wake_up_time) {
for (uint32_t i = 0; i < static_cast<uint32_t>(config::producer_repetitions * active_schedule.size() * 3); ++i) { // 3 rounds to test boundaries
block_timestamp_type block_timestamp(prod_round_1st_block_slot + i);
auto block_time = block_timestamp.to_time_point();
BOOST_CHECK_EQUAL(calculate_producer_wake_up_time(full_cpu_effort, 2, block_timestamp, producers, active_schedule, empty_watermarks), block_time);
BOOST_CHECK_EQUAL(calculate_producer_wake_up_time(full_cpu_effort, 2, block_timestamp, producers, active_schedule, empty_watermarks), std::optional<fc::time_point>{block_time});
}
}
{ // We have all producers in active_schedule configured, we should produce every block
Expand All @@ -161,7 +161,7 @@ BOOST_AUTO_TEST_CASE(test_calculate_producer_wake_up_time) {
for (uint32_t i = 0; i < static_cast<uint32_t>(config::producer_repetitions * active_schedule.size() * 3); ++i) { // 3 rounds to test boundaries
block_timestamp_type block_timestamp(prod_round_1st_block_slot + i);
auto block_time = block_timestamp.to_time_point();
BOOST_CHECK_EQUAL(calculate_producer_wake_up_time(full_cpu_effort, 2, block_timestamp, producers, active_schedule, empty_watermarks), block_time);
BOOST_CHECK_EQUAL(calculate_producer_wake_up_time(full_cpu_effort, 2, block_timestamp, producers, active_schedule, empty_watermarks), std::optional<fc::time_point>{block_time});
}
}
{ // We have all producers in active_schedule of 21 (plus a couple of extra producers configured), we should produce every block
Expand All @@ -179,7 +179,7 @@ BOOST_AUTO_TEST_CASE(test_calculate_producer_wake_up_time) {
for (uint32_t i = 0; i < static_cast<uint32_t>(config::producer_repetitions * active_schedule.size() * 3); ++i) { // 3 rounds to test boundaries
block_timestamp_type block_timestamp(prod_round_1st_block_slot + i);
auto block_time = block_timestamp.to_time_point();
BOOST_CHECK_EQUAL(calculate_producer_wake_up_time(full_cpu_effort, 2, block_timestamp, producers, active_schedule, empty_watermarks), block_time);
BOOST_CHECK_EQUAL(calculate_producer_wake_up_time(full_cpu_effort, 2, block_timestamp, producers, active_schedule, empty_watermarks), std::optional<fc::time_point>{block_time});
}
}
{ // Tests for when we only have a subset of all active producers, we do not produce all blocks, only produce blocks for our round
Expand All @@ -194,67 +194,67 @@ BOOST_AUTO_TEST_CASE(test_calculate_producer_wake_up_time) {
std::set<account_name> producers = { "initb"_n };
block_timestamp_type block_timestamp(prod_round_1st_block_slot);
auto expected_block_time = block_timestamp_type(prod_round_1st_block_slot + config::producer_repetitions).to_time_point();
BOOST_CHECK_EQUAL(calculate_producer_wake_up_time(full_cpu_effort, 2, block_timestamp_type{block_timestamp.slot-1}, producers, active_schedule, empty_watermarks), expected_block_time); // same
BOOST_CHECK_EQUAL(calculate_producer_wake_up_time(full_cpu_effort, 2, block_timestamp_type{block_timestamp.slot+config::producer_repetitions-1}, producers, active_schedule, empty_watermarks), expected_block_time); // same
BOOST_CHECK_EQUAL(calculate_producer_wake_up_time(full_cpu_effort, 2, block_timestamp_type{block_timestamp.slot+config::producer_repetitions-2}, producers, active_schedule, empty_watermarks), expected_block_time); // same
BOOST_CHECK_EQUAL(calculate_producer_wake_up_time(full_cpu_effort, 2, block_timestamp_type{block_timestamp.slot+config::producer_repetitions-3}, producers, active_schedule, empty_watermarks), expected_block_time); // same
BOOST_CHECK_EQUAL(calculate_producer_wake_up_time(full_cpu_effort, 2, block_timestamp_type{block_timestamp.slot-1}, producers, active_schedule, empty_watermarks), std::optional<fc::time_point>{expected_block_time}); // same
BOOST_CHECK_EQUAL(calculate_producer_wake_up_time(full_cpu_effort, 2, block_timestamp_type{block_timestamp.slot+config::producer_repetitions-1}, producers, active_schedule, empty_watermarks), std::optional<fc::time_point>{expected_block_time}); // same
BOOST_CHECK_EQUAL(calculate_producer_wake_up_time(full_cpu_effort, 2, block_timestamp_type{block_timestamp.slot+config::producer_repetitions-2}, producers, active_schedule, empty_watermarks), std::optional<fc::time_point>{expected_block_time}); // same
BOOST_CHECK_EQUAL(calculate_producer_wake_up_time(full_cpu_effort, 2, block_timestamp_type{block_timestamp.slot+config::producer_repetitions-3}, producers, active_schedule, empty_watermarks), std::optional<fc::time_point>{expected_block_time}); // same
// current which gives same expected
BOOST_CHECK_EQUAL(calculate_producer_wake_up_time(full_cpu_effort, 2, block_timestamp_type{block_timestamp.slot+config::producer_repetitions}, producers, active_schedule, empty_watermarks), expected_block_time);
BOOST_CHECK_EQUAL(calculate_producer_wake_up_time(full_cpu_effort, 2, block_timestamp_type{block_timestamp.slot+config::producer_repetitions}, producers, active_schedule, empty_watermarks), std::optional<fc::time_point>{expected_block_time});
expected_block_time += fc::microseconds(config::block_interval_us);
BOOST_CHECK_EQUAL(calculate_producer_wake_up_time(full_cpu_effort, 2, block_timestamp_type{block_timestamp.slot+config::producer_repetitions+1}, producers, active_schedule, empty_watermarks), expected_block_time);
BOOST_CHECK_EQUAL(calculate_producer_wake_up_time(full_cpu_effort, 2, block_timestamp_type{block_timestamp.slot+config::producer_repetitions+1}, producers, active_schedule, empty_watermarks), std::optional<fc::time_point>{expected_block_time});

// inita is first in the schedule, prod_round_1st_block_slot is block time of the first block, so will return the next block time as that is when current should be produced
producers = std::set<account_name>{ "inita"_n };
block_timestamp = block_timestamp_type{prod_round_1st_block_slot};
expected_block_time = block_timestamp.to_time_point();
BOOST_CHECK_EQUAL(calculate_producer_wake_up_time(full_cpu_effort, 2, block_timestamp_type{block_timestamp.slot-1}, producers, active_schedule, empty_watermarks), expected_block_time); // same
BOOST_CHECK_EQUAL(calculate_producer_wake_up_time(full_cpu_effort, 2, block_timestamp_type{block_timestamp.slot-2}, producers, active_schedule, empty_watermarks), expected_block_time); // same
BOOST_CHECK_EQUAL(calculate_producer_wake_up_time(full_cpu_effort, 2, block_timestamp_type{block_timestamp.slot-3}, producers, active_schedule, empty_watermarks), expected_block_time); // same
BOOST_CHECK_EQUAL(calculate_producer_wake_up_time(full_cpu_effort, 2, block_timestamp_type{block_timestamp.slot-1}, producers, active_schedule, empty_watermarks), std::optional<fc::time_point>{expected_block_time}); // same
BOOST_CHECK_EQUAL(calculate_producer_wake_up_time(full_cpu_effort, 2, block_timestamp_type{block_timestamp.slot-2}, producers, active_schedule, empty_watermarks), std::optional<fc::time_point>{expected_block_time}); // same
BOOST_CHECK_EQUAL(calculate_producer_wake_up_time(full_cpu_effort, 2, block_timestamp_type{block_timestamp.slot-3}, producers, active_schedule, empty_watermarks), std::optional<fc::time_point>{expected_block_time}); // same
for (size_t i = 0; i < config::producer_repetitions; ++i) {
expected_block_time = block_timestamp_type(prod_round_1st_block_slot+i).to_time_point();
BOOST_CHECK_EQUAL(calculate_producer_wake_up_time(full_cpu_effort, 2, block_timestamp, producers, active_schedule, empty_watermarks), expected_block_time);
BOOST_CHECK_EQUAL(calculate_producer_wake_up_time(full_cpu_effort, 2, block_timestamp, producers, active_schedule, empty_watermarks), std::optional<fc::time_point>{expected_block_time});
block_timestamp = block_timestamp.next();
}
expected_block_time = block_timestamp.to_time_point();
BOOST_CHECK_NE(calculate_producer_wake_up_time(full_cpu_effort, 2, block_timestamp, producers, active_schedule, empty_watermarks), expected_block_time); // end of round, so not the next
BOOST_CHECK_NE(calculate_producer_wake_up_time(full_cpu_effort, 2, block_timestamp, producers, active_schedule, empty_watermarks), std::optional<fc::time_point>{expected_block_time}); // end of round, so not the next

// initc is third in the schedule, verify its wake-up time is as expected
producers = std::set<account_name>{ "initc"_n };
block_timestamp = block_timestamp_type(prod_round_1st_block_slot);
// expect 2*producer_repetitions since we expect wake-up time to be after the first two rounds
expected_block_time = block_timestamp_type(prod_round_1st_block_slot + 2*config::producer_repetitions).to_time_point();
BOOST_CHECK_EQUAL(calculate_producer_wake_up_time(full_cpu_effort, 2, block_timestamp, producers, active_schedule, empty_watermarks), expected_block_time);
BOOST_CHECK_EQUAL(calculate_producer_wake_up_time(full_cpu_effort, 2, block_timestamp, producers, active_schedule, empty_watermarks), std::optional<fc::time_point>{expected_block_time});

// inith, initk - configured for 2 of the 21 producers. inith is 8th in schedule, initk is 11th in schedule
producers = std::set<account_name>{ "inith"_n, "initk"_n };
block_timestamp = block_timestamp_type(prod_round_1st_block_slot);
// expect to produce after 7 rounds since inith is 8th
expected_block_time = block_timestamp_type(prod_round_1st_block_slot + 7*config::producer_repetitions).to_time_point();
BOOST_CHECK_EQUAL(calculate_producer_wake_up_time(full_cpu_effort, 2, block_timestamp, producers, active_schedule, empty_watermarks), expected_block_time);
BOOST_CHECK_EQUAL(calculate_producer_wake_up_time(full_cpu_effort, 2, block_timestamp, producers, active_schedule, empty_watermarks), std::optional<fc::time_point>{expected_block_time});
// give it a time after inith otherwise would return inith time
block_timestamp = block_timestamp_type(prod_round_1st_block_slot + 8*config::producer_repetitions); // after inith round
// expect to produce after 10 rounds since inith is 11th
expected_block_time = block_timestamp_type(prod_round_1st_block_slot + 10*config::producer_repetitions).to_time_point();
BOOST_CHECK_EQUAL(calculate_producer_wake_up_time(full_cpu_effort, 2, block_timestamp, producers, active_schedule, empty_watermarks), expected_block_time);
BOOST_CHECK_EQUAL(calculate_producer_wake_up_time(full_cpu_effort, 2, block_timestamp, producers, active_schedule, empty_watermarks), std::optional<fc::time_point>{expected_block_time});

// cpu_effort at 50%, initc
constexpr fc::microseconds half_cpu_effort = fc::microseconds{eosio::chain::config::block_interval_us / 2u};
producers = std::set<account_name>{ "initc"_n };
block_timestamp = block_timestamp_type(prod_round_1st_block_slot);
expected_block_time = block_timestamp_type(prod_round_1st_block_slot + 2*config::producer_repetitions).to_time_point();
// first in round is not affected by cpu effort
BOOST_CHECK_EQUAL(calculate_producer_wake_up_time(half_cpu_effort, 2, block_timestamp, producers, active_schedule, empty_watermarks), expected_block_time);
BOOST_CHECK_EQUAL(calculate_producer_wake_up_time(half_cpu_effort, 2, block_timestamp, producers, active_schedule, empty_watermarks), std::optional<fc::time_point>{expected_block_time});
block_timestamp = block_timestamp_type(prod_round_1st_block_slot + 2*config::producer_repetitions + 1);
// second in round is 50% sooner
expected_block_time = block_timestamp.to_time_point();
expected_block_time -= fc::microseconds(half_cpu_effort);
BOOST_CHECK_EQUAL(calculate_producer_wake_up_time(half_cpu_effort, 2, block_timestamp, producers, active_schedule, empty_watermarks), expected_block_time);
BOOST_CHECK_EQUAL(calculate_producer_wake_up_time(half_cpu_effort, 2, block_timestamp, producers, active_schedule, empty_watermarks), std::optional<fc::time_point>{expected_block_time});
// third in round is 2*50% sooner
block_timestamp = block_timestamp_type(prod_round_1st_block_slot + 2*config::producer_repetitions + 2);
// second in round is 50% sooner
expected_block_time = block_timestamp.to_time_point();
expected_block_time -= fc::microseconds(2*half_cpu_effort.count());
BOOST_CHECK_EQUAL(calculate_producer_wake_up_time(half_cpu_effort, 2, block_timestamp, producers, active_schedule, empty_watermarks), expected_block_time);
BOOST_CHECK_EQUAL(calculate_producer_wake_up_time(half_cpu_effort, 2, block_timestamp, producers, active_schedule, empty_watermarks), std::optional<fc::time_point>{expected_block_time});
}
{ // test watermark
std::vector<chain::producer_authority> active_schedule{ // 21
Expand All @@ -270,15 +270,15 @@ BOOST_AUTO_TEST_CASE(test_calculate_producer_wake_up_time) {
// initc, with no watermarks
producers = std::set<account_name>{ "initc"_n };
auto expected_block_time = block_timestamp_type(prod_round_1st_block_slot + 2*config::producer_repetitions).to_time_point(); // without watermark
BOOST_CHECK_EQUAL(calculate_producer_wake_up_time(full_cpu_effort, 2, block_timestamp, producers, active_schedule, empty_watermarks), expected_block_time);
BOOST_CHECK_EQUAL(calculate_producer_wake_up_time(full_cpu_effort, 2, block_timestamp, producers, active_schedule, empty_watermarks), std::optional<fc::time_point>{expected_block_time});
// add watermark at first block, first block should not be allowed, wake-up time should be after first block of initc
prod_watermarks.consider_new_watermark("initc"_n, 2, block_timestamp_type((prod_round_1st_block_slot + 2*config::producer_repetitions + 1))); // +1 since watermark is in block production time
expected_block_time = block_timestamp_type(prod_round_1st_block_slot + 2*config::producer_repetitions + 1).to_time_point(); // with watermark, wait until next
BOOST_CHECK_EQUAL(calculate_producer_wake_up_time(full_cpu_effort, 2, block_timestamp, producers, active_schedule, prod_watermarks), expected_block_time);
BOOST_CHECK_EQUAL(calculate_producer_wake_up_time(full_cpu_effort, 2, block_timestamp, producers, active_schedule, prod_watermarks), std::optional<fc::time_point>{expected_block_time});
// add watermark at first 2 blocks, first & second block should not be allowed, wake-up time should be after second block of initc
prod_watermarks.consider_new_watermark("initc"_n, 2, block_timestamp_type((prod_round_1st_block_slot + 2*config::producer_repetitions + 1 + 1)));
expected_block_time = block_timestamp_type(prod_round_1st_block_slot + 2*config::producer_repetitions + 2).to_time_point(); // with watermark, wait until next
BOOST_CHECK_EQUAL(calculate_producer_wake_up_time(full_cpu_effort, 2, block_timestamp, producers, active_schedule, prod_watermarks), expected_block_time);
BOOST_CHECK_EQUAL(calculate_producer_wake_up_time(full_cpu_effort, 2, block_timestamp, producers, active_schedule, prod_watermarks), std::optional<fc::time_point>{expected_block_time});
}
{ // actual example that caused multiple start blocks
producer_watermarks prod_watermarks;
Expand Down
Loading

0 comments on commit dfc2516

Please sign in to comment.