#![cfg(feature = "runtime-benchmarks")]
use super::*;
use frame_benchmarking::{v2::*, BenchmarkError};
use frame_system::{Pallet as System, RawOrigin};
use sp_runtime::traits::One;
fn assert_last_event<T: Config>(generic_event: <T as Config>::RuntimeEvent) {
frame_system::Pallet::<T>::assert_last_event(generic_event.into());
}
#[benchmarks]
mod benches {
use super::*;
use frame_support::traits::Hooks;
#[benchmark]
fn onboard_new_mbms() {
T::Migrations::set_fail_after(0); assert!(!Cursor::<T>::exists());
#[block]
{
Pallet::<T>::onboard_new_mbms();
}
assert_last_event::<T>(Event::UpgradeStarted { migrations: 1 }.into());
}
#[benchmark]
fn progress_mbms_none() {
T::Migrations::set_fail_after(0); assert!(!Cursor::<T>::exists());
#[block]
{
Pallet::<T>::progress_mbms(One::one());
}
}
#[benchmark]
fn exec_migration_completed() -> Result<(), BenchmarkError> {
T::Migrations::set_fail_after(0); assert_eq!(T::Migrations::len(), 1, "Setup failed");
let c = ActiveCursor { index: 1, inner_cursor: None, started_at: 0u32.into() };
let mut meter = WeightMeter::with_limit(T::MaxServiceWeight::get());
System::<T>::set_block_number(1u32.into());
#[block]
{
Pallet::<T>::exec_migration(c, false, &mut meter);
}
assert_last_event::<T>(Event::UpgradeCompleted {}.into());
Ok(())
}
#[benchmark]
fn exec_migration_skipped_historic() -> Result<(), BenchmarkError> {
T::Migrations::set_fail_after(0); assert_eq!(T::Migrations::len(), 1, "Setup failed");
let c = ActiveCursor { index: 0, inner_cursor: None, started_at: 0u32.into() };
let id: IdentifierOf<T> = T::Migrations::nth_id(0).unwrap().try_into().unwrap();
Historic::<T>::insert(id, ());
let mut meter = WeightMeter::with_limit(T::MaxServiceWeight::get());
System::<T>::set_block_number(1u32.into());
#[block]
{
Pallet::<T>::exec_migration(c, false, &mut meter);
}
assert_last_event::<T>(Event::MigrationSkipped { index: 0 }.into());
Ok(())
}
#[benchmark]
fn exec_migration_advance() -> Result<(), BenchmarkError> {
T::Migrations::set_success_after(1);
assert_eq!(T::Migrations::len(), 1, "Setup failed");
let c = ActiveCursor { index: 0, inner_cursor: None, started_at: 0u32.into() };
let mut meter = WeightMeter::with_limit(T::MaxServiceWeight::get());
System::<T>::set_block_number(1u32.into());
#[block]
{
Pallet::<T>::exec_migration(c, false, &mut meter);
}
assert_last_event::<T>(Event::MigrationAdvanced { index: 0, took: One::one() }.into());
Ok(())
}
#[benchmark]
fn exec_migration_complete() -> Result<(), BenchmarkError> {
T::Migrations::set_success_after(0);
assert_eq!(T::Migrations::len(), 1, "Setup failed");
let c = ActiveCursor { index: 0, inner_cursor: None, started_at: 0u32.into() };
let mut meter = WeightMeter::with_limit(T::MaxServiceWeight::get());
System::<T>::set_block_number(1u32.into());
#[block]
{
Pallet::<T>::exec_migration(c, false, &mut meter);
}
assert_last_event::<T>(Event::MigrationCompleted { index: 0, took: One::one() }.into());
Ok(())
}
#[benchmark]
fn exec_migration_fail() -> Result<(), BenchmarkError> {
T::Migrations::set_fail_after(0);
assert_eq!(T::Migrations::len(), 1, "Setup failed");
let c = ActiveCursor { index: 0, inner_cursor: None, started_at: 0u32.into() };
let mut meter = WeightMeter::with_limit(T::MaxServiceWeight::get());
System::<T>::set_block_number(1u32.into());
#[block]
{
Pallet::<T>::exec_migration(c, false, &mut meter);
}
assert_last_event::<T>(Event::UpgradeFailed {}.into());
Ok(())
}
#[benchmark]
fn on_init_loop() {
T::Migrations::set_fail_after(0); System::<T>::set_block_number(1u32.into());
<Pallet<T> as Hooks<BlockNumberFor<T>>>::on_runtime_upgrade();
#[block]
{
Pallet::<T>::on_initialize(1u32.into());
}
}
#[benchmark]
fn force_set_cursor() {
#[extrinsic_call]
_(RawOrigin::Root, Some(cursor::<T>()));
}
#[benchmark]
fn force_set_active_cursor() {
#[extrinsic_call]
_(RawOrigin::Root, 0, None, None);
}
#[benchmark]
fn force_onboard_mbms() {
#[extrinsic_call]
_(RawOrigin::Root);
}
#[benchmark]
fn clear_historic(n: Linear<0, { DEFAULT_HISTORIC_BATCH_CLEAR_SIZE * 2 }>) {
let id_max_len = <T as Config>::IdentifierMaxLen::get();
assert!(id_max_len >= 4, "Precondition violated");
for i in 0..DEFAULT_HISTORIC_BATCH_CLEAR_SIZE * 2 {
let id = IdentifierOf::<T>::truncate_from(
i.encode().into_iter().cycle().take(id_max_len as usize).collect::<Vec<_>>(),
);
Historic::<T>::insert(&id, ());
}
#[extrinsic_call]
_(
RawOrigin::Root,
HistoricCleanupSelector::Wildcard { limit: n.into(), previous_cursor: None },
);
}
fn cursor<T: Config>() -> CursorOf<T> {
MigrationCursor::Active(ActiveCursor {
index: u32::MAX,
inner_cursor: None,
started_at: 0u32.into(),
})
}
impl_benchmark_test_suite!(Pallet, crate::mock::new_test_ext(), crate::mock::Test);
}