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;5253fn make_scheduled_id(src: u32) -> ScheduledId {54 let slice_id: [u8; 4] = src.encode().try_into().unwrap();55 let mut id: [u8; 16] = [0; 16];56 id[..4].clone_from_slice(&slice_id);57 id58}5960616263646566fn fill_schedule<T: Config>(67 when: T::BlockNumber,68 n: u32,69 periodic: bool,70 resolved: Option<bool>,71) -> Result<(), &'static str> {72 let t = DispatchTime::At(when);73 let caller = account("user", 0, 1);7475 76 T::Currency::make_free_balance_be(&caller, T::Currency::minimum_balance());7778 for i in 0..n {79 let (call, hash) = call_and_hash::<T>(i);80 let call_or_hash = match resolved {81 Some(_) => call.into(),82 None => CallOrHashOf::<T>::Hash(hash),83 };84 let period = match periodic {85 true => Some(((i + 100).into(), 100)),86 false => None,87 };8889 let id = make_scheduled_id(i);90 let origin = frame_system::RawOrigin::Signed(caller.clone()).into();91 Scheduler::<T>::do_schedule_named(id, t, period, 0, origin, call_or_hash)?;92 }93 ensure!(94 Agenda::<T>::get(when).len() == n as usize,95 "didn't fill schedule"96 );97 Ok(())98}99100fn call_and_hash<T: Config>(i: u32) -> (<T as Config>::RuntimeCall, T::Hash) {101 102 let call: <T as Config>::RuntimeCall = frame_system::Call::remark { remark: i.encode() }.into();103 let hash = T::Hashing::hash_of(&call);104 (call, hash)105}106107benchmarks! {108 on_initialize_periodic_named_resolved {109 let s in 1 .. T::MaxScheduledPerBlock::get();110 let when = BLOCK_NUMBER.into();111 fill_schedule::<T>(when, s, true, Some(true))?;112 }: { Scheduler::<T>::on_initialize(BLOCK_NUMBER.into()); }113 verify {114 assert_eq!(System::<T>::event_count(), s);115 for i in 0..s {116 assert_eq!(Agenda::<T>::get(when + (i + 100).into()).len(), 1 as usize);117 }118 }119120 on_initialize_named_resolved {121 let s in 1 .. T::MaxScheduledPerBlock::get();122 let when = BLOCK_NUMBER.into();123 fill_schedule::<T>(when, s, false, Some(true))?;124 }: { Scheduler::<T>::on_initialize(BLOCK_NUMBER.into()); }125 verify {126 assert_eq!(System::<T>::event_count(), s);127 assert!(Agenda::<T>::iter().count() == 0);128 }129130 on_initialize_periodic {131 let s in 1 .. T::MaxScheduledPerBlock::get();132 let when = BLOCK_NUMBER.into();133 fill_schedule::<T>(when, s, true, Some(false))?;134 }: { Scheduler::<T>::on_initialize(when); }135 verify {136 assert_eq!(System::<T>::event_count(), s);137 for i in 0..s {138 assert_eq!(Agenda::<T>::get(when + (i + 100).into()).len(), 1 as usize);139 }140 }141142 on_initialize_periodic_resolved {143 let s in 1 .. T::MaxScheduledPerBlock::get();144 let when = BLOCK_NUMBER.into();145 fill_schedule::<T>(when, s, true, Some(true))?;146 }: { Scheduler::<T>::on_initialize(BLOCK_NUMBER.into()); }147 verify {148 assert_eq!(System::<T>::event_count(), s );149 for i in 0..s {150 assert_eq!(Agenda::<T>::get(when + (i + 100).into()).len(), 1 as usize);151 }152 }153154 on_initialize_aborted {155 let s in 1 .. T::MaxScheduledPerBlock::get();156 let when = BLOCK_NUMBER.into();157 fill_schedule::<T>(when, s, false, None)?;158 }: { Scheduler::<T>::on_initialize(BLOCK_NUMBER.into()); }159 verify {160 assert_eq!(System::<T>::event_count(), 0);161 }162163 on_initialize_named_aborted {164 let s in 1 .. T::MaxScheduledPerBlock::get();165 let when = BLOCK_NUMBER.into();166 fill_schedule::<T>(when, s, false, Some(false))?;167 }: { Scheduler::<T>::on_initialize(BLOCK_NUMBER.into()); }168 verify {169 }170171 on_initialize_named {172 let s in 1 .. T::MaxScheduledPerBlock::get();173 let when = BLOCK_NUMBER.into();174 fill_schedule::<T>(when, s, false, None)?;175 }: { Scheduler::<T>::on_initialize(BLOCK_NUMBER.into()); }176 verify {177 assert_eq!(System::<T>::event_count(), 0);178 }179180 on_initialize {181 let s in 1 .. T::MaxScheduledPerBlock::get();182 let when = BLOCK_NUMBER.into();183 fill_schedule::<T>(when, s, false, Some(false))?;184 }: { Scheduler::<T>::on_initialize(BLOCK_NUMBER.into()); }185 verify {186 assert_eq!(System::<T>::event_count(), s);187 assert!(Agenda::<T>::iter().count() == 0);188 }189190 on_initialize_resolved {191 let s in 1 .. T::MaxScheduledPerBlock::get();192 let when = BLOCK_NUMBER.into();193 fill_schedule::<T>(when, s, false, Some(true))?;194 }: { Scheduler::<T>::on_initialize(BLOCK_NUMBER.into()); }195 verify {196 assert_eq!(System::<T>::event_count(), s);197 assert!(Agenda::<T>::iter().count() == 0);198 }199200 schedule_named {201 let caller: T::AccountId = account("user", 0, 1);202 let origin: RawOrigin<T::AccountId> = frame_system::RawOrigin::Signed(caller.clone());203 let s in 0 .. T::MaxScheduledPerBlock::get();204 let slice_id: [u8; 4] = s.encode().try_into().unwrap();205 let mut id: [u8; 16] = [0; 16];206 id[..4].clone_from_slice(&slice_id);207 let when = BLOCK_NUMBER.into();208 let periodic = Some((T::BlockNumber::one(), 100));209 let priority = None;210 211 let inner_call = frame_system::Call::set_storage { items: vec![] }.into();212 let call = Box::new(CallOrHashOf::<T>::Value(inner_call));213 fill_schedule::<T>(when, s, true, Some(false))?;214 }: _(origin, id, when, periodic, priority, call)215 verify {216 ensure!(217 Agenda::<T>::get(when).len() == (s + 1) as usize,218 "didn't add to schedule"219 );220 }221222 cancel_named {223 let caller: T::AccountId = account("user", 0, 1);224 let origin: RawOrigin<T::AccountId> = frame_system::RawOrigin::Signed(caller.clone());225 let s in 1 .. T::MaxScheduledPerBlock::get();226 let when = BLOCK_NUMBER.into();227 let idx = s - 1;228 let id = make_scheduled_id(idx);229 fill_schedule::<T>(when, s, true, Some(false))?;230 }: _(origin, id)231 verify {232 ensure!(233 Lookup::<T>::get(id).is_none(),234 "didn't remove from lookup"235 );236 237 ensure!(238 Agenda::<T>::get(when)[idx as usize].is_none(),239 "didn't remove from schedule"240 );241 }242243 change_named_priority {244 let origin: RawOrigin<T::AccountId> = frame_system::RawOrigin::Root;245 let s in 1 .. T::MaxScheduledPerBlock::get();246 let when = BLOCK_NUMBER.into();247 let idx = s - 1;248 let id = make_scheduled_id(idx);249 let priority = 42;250 fill_schedule::<T>(when, s, true, Some(false))?;251 }: _(origin, id, priority)252 verify {253 ensure!(254 Agenda::<T>::get(when)[idx as usize].clone().unwrap().priority == priority,255 "didn't change the priority"256 );257 }258259 impl_benchmark_test_suite!(Scheduler, crate::mock::new_test_ext(), crate::mock::Test);260}