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