referrerpolicy=no-referrer-when-downgrade

pallet_membership/
benchmarking.rs

1// This file is part of Substrate.
2
3// Copyright (C) Parity Technologies (UK) Ltd.
4// SPDX-License-Identifier: Apache-2.0
5
6// Licensed under the Apache License, Version 2.0 (the "License");
7// you may not use this file except in compliance with the License.
8// You may obtain a copy of the License at
9//
10// 	http://www.apache.org/licenses/LICENSE-2.0
11//
12// Unless required by applicable law or agreed to in writing, software
13// distributed under the License is distributed on an "AS IS" BASIS,
14// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15// See the License for the specific language governing permissions and
16// limitations under the License.
17
18//! Membership pallet benchmarking.
19
20use super::{Pallet as Membership, *};
21use frame_benchmarking::v1::{account, benchmarks_instance_pallet, whitelist, BenchmarkError};
22use frame_support::{assert_ok, traits::EnsureOrigin};
23use frame_system::RawOrigin;
24
25const SEED: u32 = 0;
26
27fn set_members<T: Config<I>, I: 'static>(members: Vec<T::AccountId>, prime: Option<usize>) {
28	let reset_origin = T::ResetOrigin::try_successful_origin()
29		.expect("ResetOrigin has no successful origin required for the benchmark");
30	let prime_origin = T::PrimeOrigin::try_successful_origin()
31		.expect("PrimeOrigin has no successful origin required for the benchmark");
32
33	assert_ok!(Membership::<T, I>::reset_members(reset_origin, members.clone()));
34	if let Some(prime) = prime.map(|i| members[i].clone()) {
35		let prime_lookup = T::Lookup::unlookup(prime);
36		assert_ok!(Membership::<T, I>::set_prime(prime_origin, prime_lookup));
37	} else {
38		assert_ok!(Membership::<T, I>::clear_prime(prime_origin));
39	}
40}
41
42benchmarks_instance_pallet! {
43	add_member {
44		let m in 1 .. (T::MaxMembers::get() - 1);
45
46		let members = (0..m).map(|i| account("member", i, SEED)).collect::<Vec<T::AccountId>>();
47		set_members::<T, I>(members, None);
48		let new_member = account::<T::AccountId>("add", m, SEED);
49		let new_member_lookup = T::Lookup::unlookup(new_member.clone());
50	}: {
51		assert_ok!(Membership::<T, I>::add_member(
52			T::AddOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?,
53			new_member_lookup,
54		));
55	} verify {
56		assert!(Members::<T, I>::get().contains(&new_member));
57		#[cfg(test)] crate::mock::clean();
58	}
59
60	// the case of no prime or the prime being removed is surely cheaper than the case of
61	// reporting a new prime via `MembershipChanged`.
62	remove_member {
63		let m in 2 .. T::MaxMembers::get();
64
65		let members = (0..m).map(|i| account("member", i, SEED)).collect::<Vec<T::AccountId>>();
66		set_members::<T, I>(members.clone(), Some(members.len() - 1));
67
68		let to_remove = members.first().cloned().unwrap();
69		let to_remove_lookup = T::Lookup::unlookup(to_remove.clone());
70	}: {
71		assert_ok!(Membership::<T, I>::remove_member(
72			T::RemoveOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?,
73			to_remove_lookup,
74		));
75	} verify {
76		assert!(!Members::<T, I>::get().contains(&to_remove));
77		// prime is rejigged
78		assert!(Prime::<T, I>::get().is_some() && T::MembershipChanged::get_prime().is_some());
79		#[cfg(test)] crate::mock::clean();
80	}
81
82	// we remove a non-prime to make sure it needs to be set again.
83	swap_member {
84		let m in 2 .. T::MaxMembers::get();
85
86		let members = (0..m).map(|i| account("member", i, SEED)).collect::<Vec<T::AccountId>>();
87		set_members::<T, I>(members.clone(), Some(members.len() - 1));
88		let add = account::<T::AccountId>("member", m, SEED);
89		let add_lookup = T::Lookup::unlookup(add.clone());
90		let remove = members.first().cloned().unwrap();
91		let remove_lookup = T::Lookup::unlookup(remove.clone());
92	}: {
93		assert_ok!(Membership::<T, I>::swap_member(
94			T::SwapOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?,
95			remove_lookup,
96			add_lookup,
97		));
98	} verify {
99		assert!(!Members::<T, I>::get().contains(&remove));
100		assert!(Members::<T, I>::get().contains(&add));
101		// prime is rejigged
102		assert!(Prime::<T, I>::get().is_some());
103		#[cfg(test)] crate::mock::clean();
104	}
105
106	// er keep the prime common between incoming and outgoing to make sure it is rejigged.
107	reset_members {
108		let m in 1 .. T::MaxMembers::get();
109
110		let members = (1..m+1).map(|i| account("member", i, SEED)).collect::<Vec<T::AccountId>>();
111		set_members::<T, I>(members.clone(), Some(members.len() - 1));
112		let mut new_members = (m..2*m).map(|i| account("member", i, SEED)).collect::<Vec<T::AccountId>>();
113	}: {
114		assert_ok!(Membership::<T, I>::reset_members(
115			T::ResetOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?,
116			new_members.clone(),
117		));
118	} verify {
119		new_members.sort();
120		assert_eq!(Members::<T, I>::get(), new_members);
121		// prime is rejigged
122		assert!(Prime::<T, I>::get().is_some());
123		#[cfg(test)] crate::mock::clean();
124	}
125
126	change_key {
127		let m in 1 .. T::MaxMembers::get();
128
129		// worse case would be to change the prime
130		let members = (0..m).map(|i| account("member", i, SEED)).collect::<Vec<T::AccountId>>();
131		let prime = members.last().cloned().unwrap();
132		set_members::<T, I>(members.clone(), Some(members.len() - 1));
133
134		let add = account::<T::AccountId>("member", m, SEED);
135		let add_lookup = T::Lookup::unlookup(add.clone());
136		whitelist!(prime);
137	}: {
138		assert_ok!(Membership::<T, I>::change_key(RawOrigin::Signed(prime.clone()).into(), add_lookup));
139	} verify {
140		assert!(!Members::<T, I>::get().contains(&prime));
141		assert!(Members::<T, I>::get().contains(&add));
142		// prime is rejigged
143		assert_eq!(Prime::<T, I>::get().unwrap(), add);
144		#[cfg(test)] crate::mock::clean();
145	}
146
147	set_prime {
148		let m in 1 .. T::MaxMembers::get();
149		let members = (0..m).map(|i| account("member", i, SEED)).collect::<Vec<T::AccountId>>();
150		let prime = members.last().cloned().unwrap();
151		let prime_lookup = T::Lookup::unlookup(prime.clone());
152		set_members::<T, I>(members, None);
153	}: {
154		assert_ok!(Membership::<T, I>::set_prime(
155			T::PrimeOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?,
156			prime_lookup,
157		));
158	} verify {
159		assert!(Prime::<T, I>::get().is_some());
160		#[cfg(test)] crate::mock::clean();
161	}
162
163	clear_prime {
164		let members = (0..T::MaxMembers::get()).map(|i| account("member", i, SEED)).collect::<Vec<T::AccountId>>();
165		let prime = members.last().cloned().unwrap();
166		set_members::<T, I>(members, None);
167	}: {
168		assert_ok!(Membership::<T, I>::clear_prime(
169			T::PrimeOrigin::try_successful_origin().map_err(|_| BenchmarkError::Weightless)?,
170		));
171	} verify {
172		assert!(Prime::<T, I>::get().is_none());
173		assert!(<T::MembershipChanged>::get_prime().is_none());
174		#[cfg(test)] crate::mock::clean();
175	}
176
177	impl_benchmark_test_suite!(Membership, crate::mock::new_bench_ext(), crate::mock::Test);
178}