12345678910111213141516171819202122232425262728293031323334353637use super::*;38use frame_benchmarking::benchmarks;39use frame_support::{40 ensure,41 traits::{OnInitialize, PreimageProvider, PreimageRecipient},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;4950const BLOCK_NUMBER: u32 = 2;5152535455565758fn fill_schedule<T: Config>(59 when: T::BlockNumber,60 n: u32,61 periodic: bool,62 named: bool,63 resolved: Option<bool>,64) -> Result<(), &'static str> {65 for i in 0..n {66 67 let (call, hash) = call_and_hash::<T>(i);68 let call_or_hash = match resolved {69 Some(true) => {70 T::PreimageProvider::note_preimage(call.encode().try_into().unwrap());71 if T::PreimageProvider::have_preimage(&hash) {72 CallOrHashOf::<T>::Hash(hash)73 } else {74 call.into()75 }76 }77 Some(false) => call.into(),78 None => CallOrHashOf::<T>::Hash(hash),79 };80 let period = match periodic {81 true => Some(((i + 100).into(), 100)),82 false => None,83 };84 let t = DispatchTime::At(when);85 let origin = frame_system::RawOrigin::Root.into();86 if named {87 Scheduler::<T>::do_schedule_named(88 i.encode()89 .try_into()90 .unwrap_or([0; MAX_TASK_ID_LENGTH_IN_BYTES as usize]),91 t,92 period,93 0,94 origin,95 call_or_hash,96 )?;97 } else {98 Scheduler::<T>::do_schedule(t, period, 0, origin, call_or_hash)?;99 }100 }101 ensure!(102 Agenda::<T>::get(when).len() == n as usize,103 "didn't fill schedule"104 );105 Ok(())106}107108fn call_and_hash<T: Config>(i: u32) -> (<T as Config>::Call, T::Hash) {109 110 let call: <T as Config>::Call = frame_system::Call::remark { remark: i.encode() }.into();111 let hash = T::Hashing::hash_of(&call);112 (call, hash)113}114115benchmarks! {116 on_initialize_periodic_named_resolved {117 let s in 1 .. T::MaxScheduledPerBlock::get();118 let when = BLOCK_NUMBER.into();119 fill_schedule::<T>(when, s, true, true, Some(true))?;120 }: { Scheduler::<T>::on_initialize(BLOCK_NUMBER.into()); }121 verify {122 assert_eq!(System::<T>::event_count(), s * 2);123 for i in 0..s {124 assert_eq!(Agenda::<T>::get(when + (i + 100).into()).len(), 1 as usize);125 }126 }127128 on_initialize_named_resolved {129 let s in 1 .. T::MaxScheduledPerBlock::get();130 let when = BLOCK_NUMBER.into();131 fill_schedule::<T>(when, s, false, true, Some(true))?;132 }: { Scheduler::<T>::on_initialize(BLOCK_NUMBER.into()); }133 verify {134 assert_eq!(System::<T>::event_count(), s * 2);135 assert!(Agenda::<T>::iter().count() == 0);136 }137138 on_initialize_periodic_resolved {139 let s in 1 .. T::MaxScheduledPerBlock::get();140 let when = BLOCK_NUMBER.into();141 fill_schedule::<T>(when, s, true, false, Some(true))?;142 }: { Scheduler::<T>::on_initialize(BLOCK_NUMBER.into()); }143 verify {144 assert_eq!(System::<T>::event_count(), s * 2);145 for i in 0..s {146 assert_eq!(Agenda::<T>::get(when + (i + 100).into()).len(), 1 as usize);147 }148 }149150 on_initialize_resolved {151 let s in 1 .. T::MaxScheduledPerBlock::get();152 let when = BLOCK_NUMBER.into();153 fill_schedule::<T>(when, s, false, false, Some(true))?;154 }: { Scheduler::<T>::on_initialize(BLOCK_NUMBER.into()); }155 verify {156 assert_eq!(System::<T>::event_count(), s * 2);157 assert!(Agenda::<T>::iter().count() == 0);158 }159160 on_initialize_named_aborted {161 let s in 1 .. T::MaxScheduledPerBlock::get();162 let when = BLOCK_NUMBER.into();163 fill_schedule::<T>(when, s, false, true, None)?;164 }: { Scheduler::<T>::on_initialize(BLOCK_NUMBER.into()); }165 verify {166 assert_eq!(System::<T>::event_count(), 0);167 if let Some(delay) = T::NoPreimagePostponement::get() {168 assert_eq!(Agenda::<T>::get(when + delay).len(), s as usize);169 } else {170 assert!(Agenda::<T>::iter().count() == 0);171 }172 }173174 on_initialize_aborted {175 let s in 1 .. T::MaxScheduledPerBlock::get();176 let when = BLOCK_NUMBER.into();177 fill_schedule::<T>(when, s, false, false, None)?;178 }: { Scheduler::<T>::on_initialize(BLOCK_NUMBER.into()); }179 verify {180 assert_eq!(System::<T>::event_count(), 0);181 if let Some(delay) = T::NoPreimagePostponement::get() {182 assert_eq!(Agenda::<T>::get(when + delay).len(), s as usize);183 } else {184 assert!(Agenda::<T>::iter().count() == 0);185 }186 }187188 on_initialize_periodic_named {189 let s in 1 .. T::MaxScheduledPerBlock::get();190 let when = BLOCK_NUMBER.into();191 fill_schedule::<T>(when, s, true, true, Some(false))?;192 }: { Scheduler::<T>::on_initialize(BLOCK_NUMBER.into()); }193 verify {194 assert_eq!(System::<T>::event_count(), s);195 for i in 0..s {196 assert_eq!(Agenda::<T>::get(when + (i + 100).into()).len(), 1 as usize);197 }198 }199200 on_initialize_periodic {201 let s in 1 .. T::MaxScheduledPerBlock::get();202 let when = BLOCK_NUMBER.into();203 fill_schedule::<T>(when, s, true, false, Some(false))?;204 }: { Scheduler::<T>::on_initialize(when); }205 verify {206 assert_eq!(System::<T>::event_count(), s);207 for i in 0..s {208 assert_eq!(Agenda::<T>::get(when + (i + 100).into()).len(), 1 as usize);209 }210 }211212 on_initialize_named {213 let s in 1 .. T::MaxScheduledPerBlock::get();214 let when = BLOCK_NUMBER.into();215 fill_schedule::<T>(when, s, false, true, Some(false))?;216 }: { Scheduler::<T>::on_initialize(BLOCK_NUMBER.into()); }217 verify {218 assert_eq!(System::<T>::event_count(), s);219 assert!(Agenda::<T>::iter().count() == 0);220 }221222 on_initialize {223 let s in 1 .. T::MaxScheduledPerBlock::get();224 let when = BLOCK_NUMBER.into();225 fill_schedule::<T>(when, s, false, false, Some(false))?;226 }: { Scheduler::<T>::on_initialize(BLOCK_NUMBER.into()); }227 verify {228 assert_eq!(System::<T>::event_count(), s);229 assert!(Agenda::<T>::iter().count() == 0);230 }231232 schedule_named {233 let s in 0 .. T::MaxScheduledPerBlock::get();234 let id = s.encode().try_into().unwrap_or([0; MAX_TASK_ID_LENGTH_IN_BYTES as usize]);235 let when = BLOCK_NUMBER.into();236 let periodic = Some((T::BlockNumber::one(), 100));237 let priority = 0;238 239 let inner_call = frame_system::Call::set_storage { items: vec![] }.into();240 let call = Box::new(CallOrHashOf::<T>::Value(inner_call));241242 fill_schedule::<T>(when, s, true, true, Some(false))?;243 }: _(RawOrigin::Root, id, when, periodic, priority, call)244 verify {245 ensure!(246 Agenda::<T>::get(when).len() == (s + 1) as usize,247 "didn't add to schedule"248 );249 }250251 cancel_named {252 let s in 1 .. T::MaxScheduledPerBlock::get();253 let when = BLOCK_NUMBER.into();254 let id = 0.encode().try_into().unwrap_or([0; MAX_TASK_ID_LENGTH_IN_BYTES as usize]);255256 fill_schedule::<T>(when, s, true, true, Some(false))?;257 }: _(RawOrigin::Root, id)258 verify {259 ensure!(260 Lookup::<T>::get(id).is_none(),261 "didn't remove from lookup"262 );263 264 ensure!(265 Agenda::<T>::get(when)[0].is_none(),266 "didn't remove from schedule"267 );268 }269270 impl_benchmark_test_suite!(Scheduler, crate::mock::new_test_ext(), crate::mock::Test);271}