mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-04-26 15:47:58 +00:00
2a8ca4ceb2
* feat: Add try_state for message_queue * Update frame/message-queue/src/lib.rs change if let to while let and modify bump_service_head function Co-authored-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * feat: update try_state, add checks for storage * fix: add try_state builder for remaining tests * Update frame/message-queue/src/mock.rs Co-authored-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * chore: assert statement to ensure * Fix tests Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Use ensure instead of assert Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Fix function signature and feature gate Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Cleanup code Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> --------- Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> Co-authored-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> Co-authored-by: Juan <juangirini@gmail.com>
189 lines
5.8 KiB
Rust
189 lines
5.8 KiB
Rust
// This file is part of Substrate.
|
|
|
|
// Copyright (C) Parity Technologies (UK) Ltd.
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
//! Std setup helpers for testing and benchmarking.
|
|
//!
|
|
//! Cannot be put into mock.rs since benchmarks require no-std and mock.rs is std.
|
|
|
|
use crate::*;
|
|
use frame_support::traits::Defensive;
|
|
|
|
/// Converts `Self` into a `Weight` by using `Self` for all components.
|
|
pub trait IntoWeight {
|
|
fn into_weight(self) -> Weight;
|
|
}
|
|
|
|
impl IntoWeight for u64 {
|
|
fn into_weight(self) -> Weight {
|
|
Weight::from_parts(self, self)
|
|
}
|
|
}
|
|
|
|
/// Mocked message origin for testing.
|
|
#[derive(Copy, Clone, Eq, PartialEq, Encode, Decode, MaxEncodedLen, TypeInfo, Debug)]
|
|
pub enum MessageOrigin {
|
|
Here,
|
|
There,
|
|
Everywhere(u32),
|
|
}
|
|
|
|
impl From<u32> for MessageOrigin {
|
|
fn from(i: u32) -> Self {
|
|
Self::Everywhere(i)
|
|
}
|
|
}
|
|
|
|
/// Processes any message and consumes `(REQUIRED_WEIGHT, REQUIRED_WEIGHT)` weight.
|
|
///
|
|
/// Returns [ProcessMessageError::Overweight] error if the weight limit is not sufficient.
|
|
pub struct NoopMessageProcessor<Origin, const REQUIRED_WEIGHT: u64 = 1>(PhantomData<Origin>);
|
|
impl<Origin, const REQUIRED_WEIGHT: u64> ProcessMessage
|
|
for NoopMessageProcessor<Origin, REQUIRED_WEIGHT>
|
|
where
|
|
Origin: codec::FullCodec + MaxEncodedLen + Clone + Eq + PartialEq + TypeInfo + Debug,
|
|
{
|
|
type Origin = Origin;
|
|
|
|
fn process_message(
|
|
_message: &[u8],
|
|
_origin: Self::Origin,
|
|
meter: &mut WeightMeter,
|
|
_id: &mut [u8; 32],
|
|
) -> Result<bool, ProcessMessageError> {
|
|
let required = Weight::from_parts(REQUIRED_WEIGHT, REQUIRED_WEIGHT);
|
|
|
|
if meter.try_consume(required).is_ok() {
|
|
Ok(true)
|
|
} else {
|
|
Err(ProcessMessageError::Overweight(required))
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Create a message from the given data.
|
|
pub fn msg<N: Get<u32>>(x: &str) -> BoundedSlice<u8, N> {
|
|
BoundedSlice::defensive_truncate_from(x.as_bytes())
|
|
}
|
|
|
|
pub fn vmsg(x: &str) -> Vec<u8> {
|
|
x.as_bytes().to_vec()
|
|
}
|
|
|
|
/// Create a page from a single message.
|
|
pub fn page<T: Config>(msg: &[u8]) -> PageOf<T> {
|
|
PageOf::<T>::from_message::<T>(msg.try_into().unwrap())
|
|
}
|
|
|
|
pub fn single_page_book<T: Config>() -> BookStateOf<T> {
|
|
BookState { begin: 0, end: 1, count: 1, message_count: 1, size: 1, ..Default::default() }
|
|
}
|
|
|
|
pub fn empty_book<T: Config>() -> BookStateOf<T> {
|
|
BookState { begin: 0, end: 1, count: 1, ..Default::default() }
|
|
}
|
|
|
|
/// Returns a full page of messages with their index as payload and the number of messages.
|
|
pub fn full_page<T: Config>() -> (PageOf<T>, usize) {
|
|
let mut msgs = 0;
|
|
let mut page = PageOf::<T>::default();
|
|
for i in 0..u32::MAX {
|
|
let r = i.using_encoded(|d| page.try_append_message::<T>(d.try_into().unwrap()));
|
|
if r.is_err() {
|
|
break
|
|
} else {
|
|
msgs += 1;
|
|
}
|
|
}
|
|
assert!(msgs > 0, "page must hold at least one message");
|
|
(page, msgs)
|
|
}
|
|
|
|
/// Returns a page filled with empty messages and the number of messages.
|
|
pub fn book_for<T: Config>(page: &PageOf<T>) -> BookStateOf<T> {
|
|
BookState {
|
|
count: 1,
|
|
begin: 0,
|
|
end: 1,
|
|
message_count: page.remaining.into() as u64,
|
|
size: page.remaining_size.into() as u64,
|
|
..Default::default()
|
|
}
|
|
}
|
|
|
|
/// Assert the last event that was emitted.
|
|
#[cfg(any(feature = "std", feature = "runtime-benchmarks", test))]
|
|
pub fn assert_last_event<T: Config>(generic_event: <T as Config>::RuntimeEvent) {
|
|
assert!(
|
|
!frame_system::Pallet::<T>::block_number().is_zero(),
|
|
"The genesis block has n o events"
|
|
);
|
|
frame_system::Pallet::<T>::assert_last_event(generic_event.into());
|
|
}
|
|
|
|
/// Provide a setup for `bump_service_head`.
|
|
pub fn setup_bump_service_head<T: Config>(
|
|
current: <<T as Config>::MessageProcessor as ProcessMessage>::Origin,
|
|
next: <<T as Config>::MessageProcessor as ProcessMessage>::Origin,
|
|
) {
|
|
crate::Pallet::<T>::enqueue_message(msg("1"), current);
|
|
crate::Pallet::<T>::enqueue_message(msg("1"), next);
|
|
}
|
|
|
|
/// Knit a queue into the ready-ring and write it back to storage.
|
|
pub fn knit<T: Config>(o: &<<T as Config>::MessageProcessor as ProcessMessage>::Origin) {
|
|
let mut b = BookStateFor::<T>::get(o);
|
|
b.ready_neighbours = crate::Pallet::<T>::ready_ring_knit(o).ok().defensive();
|
|
BookStateFor::<T>::insert(o, b);
|
|
}
|
|
|
|
/// Unknit a queue into the ready-ring and write it back to storage.
|
|
pub fn unknit<T: Config>(o: &<<T as Config>::MessageProcessor as ProcessMessage>::Origin) {
|
|
let mut b = BookStateFor::<T>::get(o);
|
|
crate::Pallet::<T>::ready_ring_unknit(o, b.ready_neighbours.unwrap());
|
|
b.ready_neighbours = None;
|
|
BookStateFor::<T>::insert(o, b);
|
|
}
|
|
|
|
/// Build a ring with three queues: `Here`, `There` and `Everywhere(0)`.
|
|
pub fn build_ring<T: Config>(
|
|
queues: &[<<T as Config>::MessageProcessor as ProcessMessage>::Origin],
|
|
) {
|
|
for queue in queues.iter() {
|
|
crate::Pallet::<T>::enqueue_message(msg("1"), queue.clone());
|
|
}
|
|
assert_ring::<T>(queues);
|
|
}
|
|
|
|
/// Check that the Ready Ring consists of `queues` in that exact order.
|
|
///
|
|
/// Also check that all backlinks are valid and that the first element is the service head.
|
|
pub fn assert_ring<T: Config>(
|
|
queues: &[<<T as Config>::MessageProcessor as ProcessMessage>::Origin],
|
|
) {
|
|
for (i, origin) in queues.iter().enumerate() {
|
|
let book = BookStateFor::<T>::get(origin);
|
|
assert_eq!(
|
|
book.ready_neighbours,
|
|
Some(Neighbours {
|
|
prev: queues[(i + queues.len() - 1) % queues.len()].clone(),
|
|
next: queues[(i + 1) % queues.len()].clone(),
|
|
})
|
|
);
|
|
}
|
|
assert_eq!(ServiceHead::<T>::get(), queues.first().cloned());
|
|
}
|