1#![cfg(feature = "runtime-benchmarks")]
21#![allow(unused_assignments)] use super::{mock_helpers::*, Pallet as MessageQueue, *};
24
25use frame_benchmarking::v2::*;
26use frame_support::traits::Get;
27use frame_system::RawOrigin;
28use sp_io::hashing::blake2_256;
29
30#[benchmarks(
31 where
32 <<T as Config>::MessageProcessor as ProcessMessage>::Origin: From<u32> + PartialEq,
33 <T as Config>::Size: From<u32>,
34 )]
38mod benchmarks {
39 use super::*;
40
41 #[benchmark]
43 fn ready_ring_knit() {
44 let mid: MessageOriginOf<T> = 1.into();
45 build_ring::<T>(&[0.into(), mid.clone(), 2.into()]);
46 unknit::<T>(&mid);
47 assert_ring::<T>(&[0.into(), 2.into()]);
48 let mut neighbours = None;
49
50 #[block]
51 {
52 neighbours = MessageQueue::<T>::ready_ring_knit(&mid).ok();
53 }
54
55 BookStateFor::<T>::mutate(&mid, |b| b.ready_neighbours = neighbours);
57 assert_ring::<T>(&[0.into(), 2.into(), mid]);
58 }
59
60 #[benchmark]
62 fn ready_ring_unknit() {
63 build_ring::<T>(&[0.into(), 1.into(), 2.into()]);
64 assert_ring::<T>(&[0.into(), 1.into(), 2.into()]);
65 let o: MessageOriginOf<T> = 0.into();
66 let neighbours = BookStateFor::<T>::get(&o).ready_neighbours.unwrap();
67
68 #[block]
69 {
70 MessageQueue::<T>::ready_ring_unknit(&o, neighbours);
71 }
72
73 assert_ring::<T>(&[1.into(), 2.into()]);
74 }
75
76 #[benchmark]
78 fn service_queue_base() {
79 #[block]
80 {
81 MessageQueue::<T>::service_queue(0.into(), &mut WeightMeter::new(), Weight::MAX);
82 }
83 }
84
85 #[benchmark]
87 fn service_page_base_completion() {
88 let origin: MessageOriginOf<T> = 0.into();
89 let page = PageOf::<T>::default();
90 Pages::<T>::insert(&origin, 0, &page);
91 let mut book_state = single_page_book::<T>();
92 let mut meter = WeightMeter::new();
93 let limit = Weight::MAX;
94
95 #[block]
96 {
97 MessageQueue::<T>::service_page(&origin, &mut book_state, &mut meter, limit);
98 }
99 }
100
101 #[benchmark]
103 fn service_page_base_no_completion() {
104 let origin: MessageOriginOf<T> = 0.into();
105 let mut page = PageOf::<T>::default();
106 page.first = 1.into();
108 page.remaining = 1.into();
109 Pages::<T>::insert(&origin, 0, &page);
110 let mut book_state = single_page_book::<T>();
111 let mut meter = WeightMeter::new();
112 let limit = Weight::MAX;
113
114 #[block]
115 {
116 MessageQueue::<T>::service_page(&origin, &mut book_state, &mut meter, limit);
117 }
118 }
119
120 #[benchmark]
122 fn service_page_item() {
123 let msg = vec![1u8; MaxMessageLenOf::<T>::get() as usize];
124 let mut page = page::<T>(&msg.clone());
125 let mut book = book_for::<T>(&page);
126 assert!(page.peek_first().is_some(), "There is one message");
127 let mut weight = WeightMeter::new();
128
129 #[block]
130 {
131 let status = MessageQueue::<T>::service_page_item(
132 &0u32.into(),
133 0,
134 &mut book,
135 &mut page,
136 &mut weight,
137 Weight::MAX,
138 );
139 assert_eq!(status, ItemExecutionStatus::Executed(true));
140 }
141
142 assert_last_event::<T>(
144 Event::Processed {
145 id: blake2_256(&msg).into(),
146 origin: 0.into(),
147 weight_used: 1.into_weight(),
148 success: true,
149 }
150 .into(),
151 );
152 let (_, processed, _) = page.peek_index(0).unwrap();
153 assert!(processed);
154 assert_eq!(book.message_count, 0);
155 }
156
157 #[benchmark]
159 fn bump_service_head() {
160 setup_bump_service_head::<T>(0.into(), 10.into());
161 let mut weight = WeightMeter::new();
162
163 #[block]
164 {
165 MessageQueue::<T>::bump_service_head(&mut weight);
166 }
167
168 assert_eq!(ServiceHead::<T>::get().unwrap(), 10u32.into());
169 assert_eq!(weight.consumed(), T::WeightInfo::bump_service_head());
170 }
171
172 #[benchmark]
174 fn set_service_head() {
175 setup_bump_service_head::<T>(0.into(), 1.into());
176 let mut weight = WeightMeter::new();
177 assert_eq!(ServiceHead::<T>::get().unwrap(), 0u32.into());
178
179 #[block]
180 {
181 assert!(MessageQueue::<T>::set_service_head(&mut weight, &1u32.into()).unwrap());
182 }
183
184 assert_eq!(ServiceHead::<T>::get().unwrap(), 1u32.into());
185 assert_eq!(weight.consumed(), T::WeightInfo::set_service_head());
186 }
187
188 #[benchmark]
189 fn reap_page() {
190 let origin: MessageOriginOf<T> = 0.into();
192 let mut book = single_page_book::<T>();
193 let (page, msgs) = full_page::<T>();
194
195 for p in 0..T::MaxStale::get() * T::MaxStale::get() {
196 if p == 0 {
197 Pages::<T>::insert(&origin, p, &page);
198 }
199 book.end += 1;
200 book.count += 1;
201 book.message_count += msgs as u64;
202 book.size += page.remaining_size.into() as u64;
203 }
204 book.begin = book.end - T::MaxStale::get();
205 BookStateFor::<T>::insert(&origin, &book);
206 assert!(Pages::<T>::contains_key(&origin, 0));
207
208 #[extrinsic_call]
209 _(RawOrigin::Signed(whitelisted_caller()), 0u32.into(), 0);
210
211 assert_last_event::<T>(Event::PageReaped { origin: 0.into(), index: 0 }.into());
212 assert!(!Pages::<T>::contains_key(&origin, 0));
213 }
214
215 #[benchmark]
220 fn execute_overweight_page_removed() {
221 let origin: MessageOriginOf<T> = 0.into();
222 let (mut page, msgs) = full_page::<T>();
223 for _ in 1..msgs {
225 page.skip_first(true);
226 }
227 page.skip_first(false);
228 let book = book_for::<T>(&page);
229 Pages::<T>::insert(&origin, 0, &page);
230 BookStateFor::<T>::insert(&origin, &book);
231
232 #[block]
233 {
234 MessageQueue::<T>::execute_overweight(
235 RawOrigin::Signed(whitelisted_caller()).into(),
236 0u32.into(),
237 0u32,
238 ((msgs - 1) as u32).into(),
239 Weight::MAX,
240 )
241 .unwrap();
242 }
243
244 assert_last_event::<T>(
245 Event::Processed {
246 id: blake2_256(&((msgs - 1) as u32).encode()).into(),
247 origin: 0.into(),
248 weight_used: Weight::from_parts(1, 1),
249 success: true,
250 }
251 .into(),
252 );
253 assert!(!Pages::<T>::contains_key(&origin, 0), "Page must be removed");
254 }
255
256 #[benchmark]
258 fn execute_overweight_page_updated() {
259 let origin: MessageOriginOf<T> = 0.into();
260 let (mut page, msgs) = full_page::<T>();
261 for _ in 0..msgs {
263 page.skip_first(false);
264 }
265 let book = book_for::<T>(&page);
266 Pages::<T>::insert(&origin, 0, &page);
267 BookStateFor::<T>::insert(&origin, &book);
268
269 #[block]
270 {
271 MessageQueue::<T>::execute_overweight(
272 RawOrigin::Signed(whitelisted_caller()).into(),
273 0u32.into(),
274 0u32,
275 ((msgs - 1) as u32).into(),
276 Weight::MAX,
277 )
278 .unwrap();
279 }
280
281 assert_last_event::<T>(
282 Event::Processed {
283 id: blake2_256(&((msgs - 1) as u32).encode()).into(),
284 origin: 0.into(),
285 weight_used: Weight::from_parts(1, 1),
286 success: true,
287 }
288 .into(),
289 );
290 assert!(Pages::<T>::contains_key(&origin, 0), "Page must be updated");
291 }
292
293 impl_benchmark_test_suite! {
294 MessageQueue,
295 crate::mock::new_test_ext::<crate::integration_test::Test>(),
296 crate::integration_test::Test
297 }
298}