12345678910111213141516171819202122232425262728293031323334353637use super::*;38use frame_benchmarking::{benchmarks, account};39use frame_support::{40 ensure,41 traits::{OnInitialize},42};43use frame_system::RawOrigin;44use sp_runtime::traits::Hash;45use sp_std::{prelude::*, vec};4647use crate::Pallet as Scheduler;48use frame_system::Pallet as System;49use frame_support::traits::Currency;5051const BLOCK_NUMBER: u32 = 2;5253545556575859fn fill_schedule<T: Config>(60 when: T::BlockNumber,61 n: u32,62 periodic: bool,63 resolved: Option<bool>,64) -> Result<(), &'static str> {65 let t = DispatchTime::At(when);66 let caller = account("user", 0, 1);6768 69 T::Currency::make_free_balance_be(&caller, T::Currency::minimum_balance());7071 for i in 0..n {72 let (call, hash) = call_and_hash::<T>(i);73 let call_or_hash = match resolved {74 Some(_) => call.into(),75 None => CallOrHashOf::<T>::Hash(hash),76 };77 let period = match periodic {78 true => Some(((i + 100).into(), 100)),79 false => None,80 };8182 let slice_id: [u8; 4] = i.encode().try_into().unwrap();83 let mut id: [u8; 16] = [0; 16];84 id[..4].clone_from_slice(&slice_id);8586 let origin = frame_system::RawOrigin::Signed(caller.clone()).into();87 Scheduler::<T>::do_schedule_named(id, t, period, 0, origin, call_or_hash)?;88 }89 ensure!(90 Agenda::<T>::get(when).len() == n as usize,91 "didn't fill schedule"92 );93 Ok(())94}9596fn call_and_hash<T: Config>(i: u32) -> (<T as Config>::Call, T::Hash) {97 98 let call: <T as Config>::Call = frame_system::Call::remark { remark: i.encode() }.into();99 let hash = T::Hashing::hash_of(&call);100 (call, hash)101}102103benchmarks! {104 on_initialize_periodic_named_resolved {105 let s in 1 .. T::MaxScheduledPerBlock::get();106 let when = BLOCK_NUMBER.into();107 fill_schedule::<T>(when, s, true, Some(true))?;108 }: { Scheduler::<T>::on_initialize(BLOCK_NUMBER.into()); }109 verify {110 assert_eq!(System::<T>::event_count(), s);111 for i in 0..s {112 assert_eq!(Agenda::<T>::get(when + (i + 100).into()).len(), 1 as usize);113 }114 }115116 on_initialize_named_resolved {117 let s in 1 .. T::MaxScheduledPerBlock::get();118 let when = BLOCK_NUMBER.into();119 fill_schedule::<T>(when, s, false, Some(true))?;120 }: { Scheduler::<T>::on_initialize(BLOCK_NUMBER.into()); }121 verify {122 assert_eq!(System::<T>::event_count(), s);123 assert!(Agenda::<T>::iter().count() == 0);124 }125126 on_initialize_periodic_resolved {127 let s in 1 .. T::MaxScheduledPerBlock::get();128 let when = BLOCK_NUMBER.into();129 fill_schedule::<T>(when, s, true, Some(true))?;130 }: { Scheduler::<T>::on_initialize(BLOCK_NUMBER.into()); }131 verify {132 assert_eq!(System::<T>::event_count(), s );133 for i in 0..s {134 assert_eq!(Agenda::<T>::get(when + (i + 100).into()).len(), 1 as usize);135 }136 }137138 on_initialize_resolved {139 let s in 1 .. T::MaxScheduledPerBlock::get();140 let when = BLOCK_NUMBER.into();141 fill_schedule::<T>(when, s, false, Some(true))?;142 }: { Scheduler::<T>::on_initialize(BLOCK_NUMBER.into()); }143 verify {144 assert_eq!(System::<T>::event_count(), s);145 assert!(Agenda::<T>::iter().count() == 0);146 }147148 schedule_named {149 let caller: T::AccountId = account("user", 0, 1);150 let origin: RawOrigin<T::AccountId> = frame_system::RawOrigin::Signed(caller.clone());151 let s in 0 .. T::MaxScheduledPerBlock::get();152 let slice_id: [u8; 4] = s.encode().try_into().unwrap();153 let mut id: [u8; 16] = [0; 16];154 id[..4].clone_from_slice(&slice_id);155 let when = BLOCK_NUMBER.into();156 let periodic = Some((T::BlockNumber::one(), 100));157 let priority = 0;158 159 let inner_call = frame_system::Call::set_storage { items: vec![] }.into();160 let call = Box::new(CallOrHashOf::<T>::Value(inner_call));161 fill_schedule::<T>(when, s, true, Some(false))?;162 }: _(origin, id, when, periodic, priority, call)163 verify {164 ensure!(165 Agenda::<T>::get(when).len() == (s + 1) as usize,166 "didn't add to schedule"167 );168 }169170 cancel_named {171 let caller: T::AccountId = account("user", 0, 1);172 let origin: RawOrigin<T::AccountId> = frame_system::RawOrigin::Signed(caller.clone());173 let s in 1 .. T::MaxScheduledPerBlock::get();174 let when = BLOCK_NUMBER.into();175 let id = 0.encode().try_into().unwrap_or([0; MAX_TASK_ID_LENGTH_IN_BYTES as usize]);176 fill_schedule::<T>(when, s, true, Some(false))?;177 }: _(origin, id)178 verify {179 ensure!(180 Lookup::<T>::get(id).is_none(),181 "didn't remove from lookup"182 );183 184 ensure!(185 Agenda::<T>::get(when)[0].is_none(),186 "didn't remove from schedule"187 );188 }189190 impl_benchmark_test_suite!(Scheduler, crate::mock::new_test_ext(), crate::mock::Test);191}