git.delta.rocks / unique-network / refs/commits / a6efbf36f2fa

difftreelog

source

pallets/scheduler/src/benchmarking.rs8.1 KiBsourcehistory
1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// This file is part of Unique Network.34// Unique Network is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (at your option) any later version.89// Unique Network is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the12// GNU General Public License for more details.1314// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.1617// Original license18// This file is part of Substrate.1920// Copyright (C) 2020-2021 Parity Technologies (UK) Ltd.21// SPDX-License-Identifier: Apache-2.02223// Licensed under the Apache License, Version 2.0 (the "License");24// you may not use this file except in compliance with the License.25// You may obtain a copy of the License at26//27// 	http://www.apache.org/licenses/LICENSE-2.028//29// Unless required by applicable law or agreed to in writing, software30// distributed under the License is distributed on an "AS IS" BASIS,31// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.32// See the License for the specific language governing permissions and33// limitations under the License.3435//! Scheduler pallet benchmarking.3637use 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}5960/// Add `n` named items to the schedule.61///62/// For `resolved`:63/// - `None`: aborted (hash without preimage)64/// - `Some(true)`: hash resolves into call if possible, plain call otherwise65/// - `Some(false)`: plain call66fn 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	// Give the sender account max funds for transfer (their account will never reasonably be killed).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	// Essentially a no-op call.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		// Essentially a no-op call.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		// Removed schedule is NONE237		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}