Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Utility batch test and zero delay impl #3226

Merged
merged 15 commits into from
Jan 11, 2025
Prev Previous commit
Next Next commit
chore: fix
wangminqi committed Jan 9, 2025
commit 0b0fe8342cb28a62b6920931106ab7db20ddf0c5
329 changes: 1 addition & 328 deletions parachain/pallets/parachain-staking/src/mock_zero_delay.rs
Original file line number Diff line number Diff line change
@@ -18,10 +18,9 @@
//! - Moonbeam `pallet_parachain_staking`

use crate as pallet_parachain_staking;
use crate::{pallet, AwardedPts, Config, InflationInfo, Points, Range};
use crate::{pallet, Config, InflationInfo, Points, Range};
use frame_support::{
construct_runtime, derive_impl, parameter_types,
traits::{OnFinalize, OnInitialize},
};
use sp_runtime::{BuildStorage, Perbill, Percent};

@@ -209,329 +208,3 @@ impl ExtBuilder {
ext
}
}

/// Rolls forward one block. Returns the new block number.
pub(crate) fn roll_one_block() -> u64 {
ParachainStaking::on_finalize(System::block_number());
Balances::on_finalize(System::block_number());
System::on_finalize(System::block_number());
System::set_block_number(System::block_number() + 1);
System::on_initialize(System::block_number());
Balances::on_initialize(System::block_number());
ParachainStaking::on_initialize(System::block_number());
System::block_number()
}

/// Rolls to the desired block. Returns the number of blocks played.
pub(crate) fn roll_to(n: u64) -> u64 {
let mut num_blocks = 0;
let mut block = System::block_number();
while block < n {
block = roll_one_block();
num_blocks += 1;
}
num_blocks
}

/// Rolls block-by-block to the beginning of the specified round.
/// This will complete the block in which the round change occurs.
/// Returns the number of blocks played.
pub(crate) fn roll_to_round_begin(round: u64) -> u64 {
let block = (round - 1) * DefaultBlocksPerRound::get() as u64;
roll_to(block)
}

/// Rolls block-by-block to the end of the specified round.
/// The block following will be the one in which the specified round change occurs.
pub(crate) fn roll_to_round_end(round: u64) -> u64 {
let block = round * DefaultBlocksPerRound::get() as u64 - 1;
roll_to(block)
}

pub(crate) fn last_event() -> RuntimeEvent {
System::events().pop().expect("Event expected").event
}

pub(crate) fn events() -> Vec<pallet::Event<Test>> {
System::events()
.into_iter()
.map(|r| r.event)
.filter_map(
|e| if let RuntimeEvent::ParachainStaking(inner) = e { Some(inner) } else { None },
)
.collect::<Vec<_>>()
}

/// Assert input equal to the last event emitted
#[macro_export]
macro_rules! assert_last_event {
($event:expr) => {
match &$event {
e => assert_eq!(*e, $crate::mock::last_event()),
}
};
}

/// Compares the system events with passed in events
/// Prints highlighted diff iff assert_eq fails
#[macro_export]
macro_rules! assert_eq_events {
($events:expr) => {
match &$events {
e => similar_asserts::assert_eq!(*e, $crate::mock::events()),
}
};
}

/// Compares the last N system events with passed in events, where N is the length of events passed
/// in.
///
/// Prints highlighted diff iff assert_eq fails.
/// The last events from frame_system will be taken in order to match the number passed to this
/// macro. If there are insufficient events from frame_system, they will still be compared; the
/// output may or may not be helpful.
///
/// Examples:
/// If frame_system has events [A, B, C, D, E] and events [C, D, E] are passed in, the result would
/// be a successful match ([C, D, E] == [C, D, E]).
///
/// If frame_system has events [A, B, C, D] and events [B, C] are passed in, the result would be an
/// error and a hopefully-useful diff will be printed between [C, D] and [B, C].
///
/// Note that events are filtered to only match parachain-staking (see events()).
#[macro_export]
macro_rules! assert_eq_last_events {
($events:expr $(,)?) => {
assert_tail_eq!($events, $crate::mock::events());
};
($events:expr, $($arg:tt)*) => {
assert_tail_eq!($events, $crate::mock::events(), $($arg)*);
};
}

/// Assert that one array is equal to the tail of the other. A more generic and testable version of
/// assert_eq_last_events.
#[macro_export]
macro_rules! assert_tail_eq {
($tail:expr, $arr:expr $(,)?) => {
if $tail.len() != 0 {
// 0-length always passes

if $tail.len() > $arr.len() {
similar_asserts::assert_eq!($tail, $arr); // will fail
}

let len_diff = $arr.len() - $tail.len();
similar_asserts::assert_eq!($tail, $arr[len_diff..]);
}
};
($tail:expr, $arr:expr, $($arg:tt)*) => {
if $tail.len() != 0 {
// 0-length always passes

if $tail.len() > $arr.len() {
similar_asserts::assert_eq!($tail, $arr, $($arg)*); // will fail
}

let len_diff = $arr.len() - $tail.len();
similar_asserts::assert_eq!($tail, $arr[len_diff..], $($arg)*);
}
};
}

/// Panics if an event is not found in the system log of events
#[macro_export]
macro_rules! assert_event_emitted {
($event:expr) => {
match &$event {
e => {
assert!(
$crate::mock::events().iter().find(|x| *x == e).is_some(),
"Event {:?} was not found in events: \n {:?}",
e,
$crate::mock::events()
);
},
}
};
}

/// Panics if an event is found in the system log of events
#[macro_export]
macro_rules! assert_event_not_emitted {
($event:expr) => {
match &$event {
e => {
assert!(
$crate::mock::events().iter().find(|x| *x == e).is_none(),
"Event {:?} was found in events: \n {:?}",
e,
$crate::mock::events()
);
},
}
};
}

// Same storage changes as EventHandler::note_author impl
pub(crate) fn set_author(round: u32, acc: u64, pts: u32) {
<Points<Test>>::mutate(round, |p| *p += pts);
<AwardedPts<Test>>::mutate(round, acc, |p| *p += pts);
}

#[test]
fn geneses() {
ExtBuilder::default()
.with_balances(vec![
(1, 1000),
(2, 300),
(3, 1100),
(4, 1100),
(5, 1100),
(6, 1100),
(7, 100),
(8, 9),
(9, 4),
])
.with_candidates(vec![(1, 500), (2, 200)])
.with_delegations(vec![(3, 1, 100), (4, 1, 100), (5, 2, 100), (6, 2, 100)])
.build()
.execute_with(|| {
assert!(System::events().is_empty());
// collators
assert_eq!(Balances::reserved_balance(&1), 500);
assert_eq!(Balances::free_balance(&1), 500);
assert!(ParachainStaking::is_candidate(&1));
assert_eq!(Balances::reserved_balance(&2), 200);
assert_eq!(Balances::free_balance(&2), 100);
assert!(ParachainStaking::is_candidate(&2));
// delegators
for x in 3..7 {
assert!(ParachainStaking::is_delegator(&x));
assert_eq!(Balances::free_balance(&x), 1000);
assert_eq!(Balances::reserved_balance(&x), 100);
}
// uninvolved
for x in 7..10 {
assert!(!ParachainStaking::is_delegator(&x));
}
assert_eq!(Balances::free_balance(&7), 100);
assert_eq!(Balances::reserved_balance(&7), 0);
assert_eq!(Balances::free_balance(&8), 9);
assert_eq!(Balances::reserved_balance(&8), 0);
assert_eq!(Balances::free_balance(&9), 4);
assert_eq!(Balances::reserved_balance(&9), 0);
});
ExtBuilder::default()
.with_balances(vec![
(1, 100),
(2, 100),
(3, 100),
(4, 100),
(5, 100),
(6, 100),
(7, 100),
(8, 100),
(9, 100),
(10, 100),
])
.with_candidates(vec![(1, 20), (2, 20), (3, 20), (4, 20), (5, 10)])
.with_delegations(vec![(6, 1, 10), (7, 1, 10), (8, 2, 10), (9, 2, 10), (10, 1, 10)])
.build()
.execute_with(|| {
assert!(System::events().is_empty());
// collators
for x in 1..5 {
assert!(ParachainStaking::is_candidate(&x));
assert_eq!(Balances::free_balance(&x), 80);
assert_eq!(Balances::reserved_balance(&x), 20);
}
assert!(ParachainStaking::is_candidate(&5));
assert_eq!(Balances::free_balance(&5), 90);
assert_eq!(Balances::reserved_balance(&5), 10);
// delegators
for x in 6..11 {
assert!(ParachainStaking::is_delegator(&x));
assert_eq!(Balances::free_balance(&x), 90);
assert_eq!(Balances::reserved_balance(&x), 10);
}
});
}

#[test]
fn roll_to_round_begin_works() {
ExtBuilder::default().build().execute_with(|| {
// these tests assume blocks-per-round of 5, as established by DefaultBlocksPerRound
assert_eq!(System::block_number(), 1); // we start on block 1

let num_blocks = roll_to_round_begin(1);
assert_eq!(System::block_number(), 1); // no-op, we're already on this round
assert_eq!(num_blocks, 0);

let num_blocks = roll_to_round_begin(2);
assert_eq!(System::block_number(), 5);
assert_eq!(num_blocks, 4);

let num_blocks = roll_to_round_begin(3);
assert_eq!(System::block_number(), 10);
assert_eq!(num_blocks, 5);
});
}

#[test]
fn roll_to_round_end_works() {
ExtBuilder::default().build().execute_with(|| {
// these tests assume blocks-per-round of 5, as established by DefaultBlocksPerRound
assert_eq!(System::block_number(), 1); // we start on block 1

let num_blocks = roll_to_round_end(1);
assert_eq!(System::block_number(), 4);
assert_eq!(num_blocks, 3);

let num_blocks = roll_to_round_end(2);
assert_eq!(System::block_number(), 9);
assert_eq!(num_blocks, 5);

let num_blocks = roll_to_round_end(3);
assert_eq!(System::block_number(), 14);
assert_eq!(num_blocks, 5);
});
}

#[test]
fn assert_tail_eq_works() {
assert_tail_eq!(vec![1, 2], vec![0, 1, 2]);

assert_tail_eq!(vec![1], vec![1]);

assert_tail_eq!(
vec![0u32; 0], // 0 length array
vec![0u32; 1] // 1-length array
);

assert_tail_eq!(vec![0u32, 0], vec![0u32, 0]);
}

#[test]
#[should_panic]
fn assert_tail_eq_panics_on_non_equal_tail() {
assert_tail_eq!(vec![2, 2], vec![0, 1, 2]);
}

#[test]
#[should_panic]
fn assert_tail_eq_panics_on_empty_arr() {
assert_tail_eq!(vec![2, 2], vec![0u32; 0]);
}

#[test]
#[should_panic]
fn assert_tail_eq_panics_on_longer_tail() {
assert_tail_eq!(vec![1, 2, 3], vec![1, 2]);
}

#[test]
#[should_panic]
fn assert_tail_eq_panics_on_unequal_elements_same_length_array() {
assert_tail_eq!(vec![1, 2, 3], vec![0, 1, 2]);
}
Original file line number Diff line number Diff line change
@@ -13,7 +13,7 @@
//
// You should have received a copy of the GNU General Public License
// along with Litentry. If not, see <https://www.gnu.org/licenses/>.
use crate::mock_zero_delay::{ExtBuilder, RuntimeCall, RuntimeOrigin, Test, Utility};
use crate::mock_zero_delay::{ExtBuilder, RuntimeCall, RuntimeOrigin, Utility};
use frame_support::assert_ok;

use crate::Call as ParachainStakingCall;