// This file is part of Bizinikiwi. // 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. use std::collections::BTreeMap; use pezframe_support::{ assert_ok, derive_impl, dispatch::{DispatchClass, DispatchInfo, GetDispatchInfo, Parameter, Pays}, dispatch_context::with_context, pezpallet_prelude::{StorageInfoTrait, ValueQuery}, parameter_types, storage::{unhashed, unhashed::contains_prefixed_key}, traits::{ ConstU32, GetCallIndex, GetCallName, GetStorageVersion, OnFinalize, OnGenesis, OnInitialize, OnRuntimeUpgrade, PalletError, PalletInfoAccess, SignedTransactionBuilder, StorageVersion, UnfilteredDispatchable, }, weights::{RuntimeDbWeight, Weight}, OrdNoBound, PartialOrdNoBound, }; use pezframe_system::offchain::{CreateSignedTransaction, CreateTransactionBase, SigningTypes}; use scale_info::{meta_type, TypeInfo}; use pezsp_io::{ hashing::{blake2_128, twox_128, twox_64}, TestExternalities, }; use pezsp_runtime::{ testing::UintAuthorityId, traits::{Block as BlockT, Dispatchable}, DispatchError, ModuleError, }; parameter_types! { /// Used to control if the storage version should be updated. storage UpdateStorageVersion: bool = false; } pub struct SomeType1; impl From for u64 { fn from(_t: SomeType1) -> Self { 0u64 } } pub struct SomeType2; impl From for u64 { fn from(_t: SomeType2) -> Self { 100u64 } } pub struct SomeType3; impl From for u64 { fn from(_t: SomeType3) -> Self { 0u64 } } pub struct SomeType4; impl From for u64 { fn from(_t: SomeType4) -> Self { 0u64 } } pub struct SomeType5; impl From for u64 { fn from(_t: SomeType5) -> Self { 0u64 } } pub struct SomeType6; impl From for u64 { fn from(_t: SomeType6) -> Self { 0u64 } } pub struct SomeType7; impl From for u64 { fn from(_t: SomeType7) -> Self { 0u64 } } pub trait SomeAssociation1 { type _1: Parameter + codec::MaxEncodedLen + TypeInfo; } impl SomeAssociation1 for u64 { type _1 = u64; } pub trait SomeAssociation2 { type _2: Parameter + codec::MaxEncodedLen + TypeInfo; } impl SomeAssociation2 for u64 { type _2 = u64; } #[pezframe_support::pezpallet] /// Pezpallet documentation // Comments should not be included in the pezpallet documentation #[pezpallet_doc("../example-pezpallet-doc.md")] #[doc = include_str!("../example-readme.md")] pub mod pezpallet { use super::*; use pezframe_support::pezpallet_prelude::*; use pezframe_system::pezpallet_prelude::*; use pezsp_runtime::DispatchResult; type BalanceOf = ::Balance; pub(crate) const STORAGE_VERSION: StorageVersion = StorageVersion::new(10); #[pezpallet::config] pub trait Config: pezframe_system::Config where ::AccountId: From + SomeAssociation1, { /// Some comment /// Some comment #[deprecated = "test 2"] #[pezpallet::constant] type MyGetParam: Get; /// Some comment /// Some comment #[pezpallet::constant] type MyGetParam2: Get; #[pezpallet::constant] type MyGetParam3: Get<::_1>; type Balance: Parameter + Default + TypeInfo; #[allow(deprecated)] type RuntimeEvent: From> + IsType<::RuntimeEvent>; } #[pezpallet::extra_constants] impl Pezpallet where T::AccountId: From + SomeAssociation1 + From, { /// Some doc /// Some doc fn some_extra() -> T::AccountId { SomeType2.into() } /// Some doc fn some_extra_extra() -> T::AccountId { SomeType1.into() } /// Some doc #[pezpallet::constant_name(SomeExtraRename)] fn some_extra_rename() -> T::AccountId { SomeType1.into() } } #[pezpallet::pezpallet] #[pezpallet::storage_version(STORAGE_VERSION)] pub struct Pezpallet(_); #[pezpallet::hooks] impl Hooks> for Pezpallet where T::AccountId: From + From + SomeAssociation1, { fn on_initialize(_: BlockNumberFor) -> Weight { let _ = T::AccountId::from(SomeType1); // Test for where clause let _ = T::AccountId::from(SomeType2); // Test for where clause Self::deposit_event(Event::Something(10)); Weight::from_parts(10, 0) } fn on_finalize(_: BlockNumberFor) { let _ = T::AccountId::from(SomeType1); // Test for where clause let _ = T::AccountId::from(SomeType2); // Test for where clause Self::deposit_event(Event::Something(20)); } fn on_runtime_upgrade() -> Weight { let _ = T::AccountId::from(SomeType1); // Test for where clause let _ = T::AccountId::from(SomeType2); // Test for where clause Self::deposit_event(Event::Something(30)); Weight::from_parts(30, 0) } fn integrity_test() { let _ = T::AccountId::from(SomeType1); // Test for where clause let _ = T::AccountId::from(SomeType2); // Test for where clause } } #[pezpallet::call] impl Pezpallet where T::AccountId: From + From + SomeAssociation1, { /// call foo doc comment put in metadata #[pezpallet::call_index(0)] #[pezpallet::weight(Weight::from_parts(*foo as u64, 0))] #[deprecated = "test"] pub fn foo( origin: OriginFor, #[pezpallet::compact] foo: u32, _bar: u32, ) -> DispatchResultWithPostInfo { let _ = foo; let _ = T::AccountId::from(SomeType1); // Test for where clause let _ = T::AccountId::from(SomeType3); // Test for where clause let _ = origin; Self::deposit_event(Event::Something(3)); Ok(().into()) } /// call foo_storage_layer doc comment put in metadata #[pezpallet::call_index(1)] #[pezpallet::weight({1})] pub fn foo_storage_layer( _origin: OriginFor, #[pezpallet::compact] foo: u32, ) -> DispatchResultWithPostInfo { Self::deposit_event(Event::Something(0)); if foo == 0 { Err(Error::::InsufficientProposersBalance)?; } Ok(().into()) } #[pezpallet::call_index(4)] #[pezpallet::weight({1})] pub fn foo_index_out_of_order(_origin: OriginFor) -> DispatchResult { Ok(()) } // Test for DispatchResult return type #[pezpallet::call_index(2)] #[pezpallet::weight({1})] pub fn foo_no_post_info(_origin: OriginFor) -> DispatchResult { Ok(()) } #[pezpallet::call_index(3)] #[pezpallet::weight({1})] pub fn check_for_dispatch_context(_origin: OriginFor) -> DispatchResult { with_context::<(), _>(|_| ()).ok_or_else(|| DispatchError::Unavailable) } #[cfg(feature = "frame-feature-testing")] #[pezpallet::call_index(5)] #[pezpallet::weight({1})] pub fn foo_feature_test(_origin: OriginFor) -> DispatchResult { Ok(()) } } #[pezpallet::error] #[derive(PartialEq, Eq)] pub enum Error { /// error doc comment put in metadata InsufficientProposersBalance, #[deprecated = "test"] NonExistentStorageValue, Code(u8), #[codec(skip)] Skipped(u128), CompactU8(#[codec(compact)] u8), #[cfg(feature = "frame-feature-testing")] FeatureTest, } #[pezpallet::event] #[pezpallet::generate_deposit(fn deposit_event)] pub enum Event where T::AccountId: SomeAssociation1 + From, { /// event doc comment put in metadata Proposed(::AccountId), #[deprecated = "test"] Spending(BalanceOf), Something(u32), SomethingElse(::_1), } #[pezpallet::storage] pub type ValueWhereClause where T::AccountId: SomeAssociation2, = StorageValue<_, ::_2>; #[pezpallet::storage] pub type Value = StorageValue; #[pezpallet::storage] #[pezpallet::storage_prefix = "Value2"] pub type RenamedValue = StorageValue; /// Test some doc #[pezpallet::type_value] pub fn MyDefault() -> u16 where T::AccountId: From + From + SomeAssociation1, { let _ = T::AccountId::from(SomeType7); // Test where clause works 4u16 } #[pezpallet::storage] pub type Map where T::AccountId: From, = StorageMap<_, Blake2_128Concat, u8, u16, ValueQuery, MyDefault>; #[pezpallet::storage] pub type Map2 = StorageMap>; #[pezpallet::storage] #[allow(deprecated)] pub type Map3 = StorageMap<_, Blake2_128Concat, u32, u64, ResultQuery::NonExistentStorageValue>>; #[pezpallet::storage] pub type DoubleMap = StorageDoubleMap<_, Blake2_128Concat, u8, Twox64Concat, u16, u32>; #[pezpallet::storage] pub type DoubleMap2 = StorageDoubleMap< Hasher1 = Twox64Concat, Key1 = u16, Hasher2 = Blake2_128Concat, Key2 = u32, Value = u64, MaxValues = ConstU32<5>, >; #[pezpallet::storage] #[allow(deprecated)] pub type DoubleMap3 = StorageDoubleMap< _, Blake2_128Concat, u32, Twox64Concat, u64, u128, ResultQuery::NonExistentStorageValue>, >; #[pezpallet::storage] #[pezpallet::getter(fn nmap)] pub type NMap = StorageNMap<_, storage::Key, u32>; #[pezpallet::storage] #[pezpallet::getter(fn nmap2)] pub type NMap2 = StorageNMap< Key = (NMapKey, NMapKey), Value = u64, MaxValues = ConstU32<11>, >; #[pezpallet::storage] #[pezpallet::getter(fn nmap3)] #[allow(deprecated)] pub type NMap3 = StorageNMap< _, (NMapKey, NMapKey), u128, ResultQuery::NonExistentStorageValue>, >; #[pezpallet::storage] #[pezpallet::getter(fn counted_nmap)] pub type CountedNMap = CountedStorageNMap<_, storage::Key, u32>; #[pezpallet::storage] #[pezpallet::getter(fn counted_nmap2)] pub type CountedNMap2 = CountedStorageNMap< Key = (NMapKey, NMapKey), Value = u64, MaxValues = ConstU32<11>, >; #[pezpallet::storage] #[pezpallet::getter(fn counted_nmap3)] #[allow(deprecated)] pub type CountedNMap3 = CountedStorageNMap< _, (NMapKey, NMapKey), u128, ResultQuery::NonExistentStorageValue>, >; #[pezpallet::storage] #[pezpallet::getter(fn conditional_value)] #[cfg(feature = "frame-feature-testing")] pub type ConditionalValue = StorageValue<_, u32>; #[cfg(feature = "frame-feature-testing")] #[pezpallet::storage] #[pezpallet::getter(fn conditional_map)] pub type ConditionalMap = StorageMap<_, Twox64Concat, u16, u32, OptionQuery, GetDefault, ConstU32<12>>; #[cfg(feature = "frame-feature-testing")] #[pezpallet::storage] #[pezpallet::getter(fn conditional_double_map)] pub type ConditionalDoubleMap = StorageDoubleMap<_, Blake2_128Concat, u8, Twox64Concat, u16, u32>; #[cfg(feature = "frame-feature-testing")] #[pezpallet::storage] #[pezpallet::getter(fn conditional_nmap)] pub type ConditionalNMap = StorageNMap<_, (storage::Key, storage::Key), u32>; #[cfg(feature = "frame-feature-testing")] #[pezpallet::storage] #[pezpallet::getter(fn conditional_counted_nmap)] pub type ConditionalCountedNMap = CountedStorageNMap< _, (storage::Key, storage::Key), u32, >; #[pezpallet::storage] #[pezpallet::storage_prefix = "RenamedCountedMap"] #[pezpallet::getter(fn counted_storage_map)] pub type SomeCountedStorageMap = CountedStorageMap; #[pezpallet::storage] #[pezpallet::unbounded] pub type Unbounded = StorageValue>; #[pezpallet::genesis_config] #[derive(pezframe_support::DefaultNoBound)] pub struct GenesisConfig where T::AccountId: From + SomeAssociation1 + From, { #[serde(skip)] _config: core::marker::PhantomData, _myfield: u32, } #[pezpallet::view_functions] impl Pezpallet where T::AccountId: From + SomeAssociation1, { /// Query value no args. pub fn get_value() -> Option { Value::::get() } /// Query value with args. pub fn get_value_with_arg(key: u16) -> Option { Map2::::get(key) } } #[pezpallet::genesis_build] impl BuildGenesisConfig for GenesisConfig where T::AccountId: From + SomeAssociation1 + From, { fn build(&self) { let _ = T::AccountId::from(SomeType1); // Test for where clause let _ = T::AccountId::from(SomeType4); // Test for where clause } } #[pezpallet::origin] #[derive( EqNoBound, RuntimeDebugNoBound, CloneNoBound, PartialEqNoBound, PartialOrdNoBound, OrdNoBound, Encode, Decode, DecodeWithMemTracking, TypeInfo, MaxEncodedLen, )] pub struct Origin(PhantomData); #[pezpallet::validate_unsigned] impl ValidateUnsigned for Pezpallet where T::AccountId: From + SomeAssociation1 + From + From, { type Call = Call; fn validate_unsigned(_source: TransactionSource, call: &Self::Call) -> TransactionValidity { let _ = T::AccountId::from(SomeType1); // Test for where clause let _ = T::AccountId::from(SomeType5); // Test for where clause if matches!(call, Call::foo_storage_layer { .. }) { return Ok(ValidTransaction::default()); } Err(TransactionValidityError::Invalid(InvalidTransaction::Call)) } } #[pezpallet::inherent] impl ProvideInherent for Pezpallet where T::AccountId: From + SomeAssociation1 + From + From, { type Call = Call; type Error = InherentError; const INHERENT_IDENTIFIER: InherentIdentifier = INHERENT_IDENTIFIER; fn create_inherent(_data: &InherentData) -> Option { let _ = T::AccountId::from(SomeType1); // Test for where clause let _ = T::AccountId::from(SomeType6); // Test for where clause Some(Call::foo_no_post_info {}) } fn is_inherent(call: &Self::Call) -> bool { matches!(call, Call::foo_no_post_info {} | Call::foo { .. }) } fn check_inherent(call: &Self::Call, _: &InherentData) -> Result<(), Self::Error> { match call { Call::foo_no_post_info {} => Ok(()), Call::foo { foo: 0, bar: 0 } => Err(InherentError::Fatal), Call::foo { .. } => Ok(()), _ => unreachable!("other calls are not inherents"), } } fn is_inherent_required(d: &InherentData) -> Result, Self::Error> { match d.get_data::(b"required") { Ok(Some(true)) => Ok(Some(InherentError::Fatal)), Ok(Some(false)) | Ok(None) => Ok(None), Err(_) => unreachable!("should not happen in tests"), } } } #[pezpallet::composite_enum] pub enum HoldReason { Staking, } #[derive(codec::Encode, pezsp_runtime::RuntimeDebug)] #[cfg_attr(feature = "std", derive(codec::Decode))] pub enum InherentError { Fatal, } impl pezframe_support::inherent::IsFatalError for InherentError { fn is_fatal_error(&self) -> bool { matches!(self, InherentError::Fatal) } } pub const INHERENT_IDENTIFIER: InherentIdentifier = *b"testpall"; } // Test that a pezpallet with non generic event and generic genesis_config is correctly handled // and that a pezpallet with the attribute without_storage_info is correctly handled. #[pezframe_support::pezpallet] pub mod pallet2 { use super::{SomeAssociation1, SomeType1, UpdateStorageVersion}; use pezframe_support::pezpallet_prelude::*; use pezframe_system::pezpallet_prelude::*; pub(crate) const STORAGE_VERSION: StorageVersion = StorageVersion::new(2); #[pezpallet::config] pub trait Config: pezframe_system::Config where ::AccountId: From + SomeAssociation1, { #[allow(deprecated)] type RuntimeEvent: From + IsType<::RuntimeEvent>; } #[pezpallet::pezpallet] #[pezpallet::storage_version(STORAGE_VERSION)] #[pezpallet::without_storage_info] pub struct Pezpallet(_); #[pezpallet::hooks] impl Hooks> for Pezpallet where T::AccountId: From + SomeAssociation1, { fn on_initialize(_: BlockNumberFor) -> Weight { Self::deposit_event(Event::Something(11)); Weight::zero() } fn on_finalize(_: BlockNumberFor) { Self::deposit_event(Event::Something(21)); } fn on_runtime_upgrade() -> Weight { Self::deposit_event(Event::Something(31)); if UpdateStorageVersion::get() { Self::in_code_storage_version().put::(); } Weight::zero() } } #[pezpallet::call] impl Pezpallet where T::AccountId: From + SomeAssociation1 {} #[pezpallet::storage] pub type SomeValue = StorageValue<_, Vec>; #[pezpallet::storage] pub type SomeCountedStorageMap = CountedStorageMap; #[pezpallet::event] #[pezpallet::generate_deposit(fn deposit_event)] pub enum Event { /// Something Something(u32), } #[pezpallet::genesis_config] pub struct GenesisConfig where T::AccountId: From + SomeAssociation1, { phantom: PhantomData, } impl Default for GenesisConfig where T::AccountId: From + SomeAssociation1, { fn default() -> Self { GenesisConfig { phantom: Default::default() } } } #[pezpallet::genesis_build] impl BuildGenesisConfig for GenesisConfig where T::AccountId: From + SomeAssociation1, { fn build(&self) {} } #[pezpallet::composite_enum] pub enum HoldReason { Governance, } #[pezpallet::composite_enum] pub enum SlashReason { Equivocation, } } /// Test that the supertrait check works when we pass some parameter to the `pezframe_system::Config`. #[pezframe_support::pezpallet] pub mod pallet3 { #[pezpallet::config] pub trait Config: pezframe_system::Config::RuntimeOrigin> { type RuntimeOrigin; } #[pezpallet::pezpallet] pub struct Pezpallet(_); } #[pezframe_support::pezpallet] pub mod pallet4 { #[pezpallet::config] pub trait Config: pezframe_system::Config {} #[pezpallet::pezpallet] pub struct Pezpallet(_); #[pezpallet::call] impl Pezpallet {} } /// Test that the supertrait check works when we pass some parameter to the `pezframe_system::Config`. #[pezframe_support::pezpallet] pub mod pallet5 { #[pezpallet::config] pub trait Config: pezframe_system::Config::RuntimeOrigin> { type RuntimeOrigin; } #[pezpallet::pezpallet] pub struct Pezpallet(_); } pezframe_support::parameter_types!( pub const MyGetParam3: u32 = 12; ); #[derive_impl(pezframe_system::config_preludes::TestDefaultConfig)] impl pezframe_system::Config for Runtime { type BaseCallFilter = pezframe_support::traits::Everything; type RuntimeOrigin = RuntimeOrigin; type Nonce = u64; type RuntimeCall = RuntimeCall; type Hash = pezsp_runtime::testing::H256; type Hashing = pezsp_runtime::traits::BlakeTwo256; type AccountId = u64; type Lookup = pezsp_runtime::traits::IdentityLookup; type Block = Block; type RuntimeEvent = RuntimeEvent; type BlockWeights = (); type BlockLength = (); type DbWeight = (); type Version = (); type PalletInfo = PalletInfo; type AccountData = (); type OnNewAccount = (); type OnKilledAccount = (); type SystemWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); type MaxConsumers = ConstU32<16>; } impl pezpallet::Config for Runtime { type RuntimeEvent = RuntimeEvent; type MyGetParam = ConstU32<10>; type MyGetParam2 = ConstU32<11>; type MyGetParam3 = MyGetParam3; type Balance = u64; } impl pallet2::Config for Runtime { type RuntimeEvent = RuntimeEvent; } impl pallet4::Config for Runtime {} #[cfg(feature = "frame-feature-testing")] impl pallet3::Config for Runtime { type RuntimeOrigin = RuntimeOrigin; } #[cfg(feature = "frame-feature-testing-2")] impl pallet5::Config for Runtime { type RuntimeOrigin = RuntimeOrigin; } pub type Header = pezsp_runtime::generic::Header; pub type Block = pezsp_runtime::generic::Block; pub type UncheckedExtrinsic = pezsp_runtime::generic::UncheckedExtrinsic< u64, RuntimeCall, UintAuthorityId, pezframe_system::CheckNonZeroSender, >; pub type UncheckedSignaturePayload = pezsp_runtime::generic::UncheckedSignaturePayload< u64, UintAuthorityId, pezframe_system::CheckNonZeroSender, >; impl SigningTypes for Runtime { type Public = UintAuthorityId; type Signature = UintAuthorityId; } impl CreateTransactionBase for Runtime where RuntimeCall: From, { type RuntimeCall = RuntimeCall; type Extrinsic = UncheckedExtrinsic; } impl CreateSignedTransaction for Runtime where RuntimeCall: From, { fn create_signed_transaction< C: pezframe_system::offchain::AppCrypto, >( call: RuntimeCall, _public: UintAuthorityId, account: u64, nonce: u64, ) -> Option { Some(UncheckedExtrinsic::new_signed( call, nonce, account.into(), pezframe_system::CheckNonZeroSender::new(), )) } } #[pezframe_support::runtime] mod runtime { #[runtime::runtime] #[runtime::derive( RuntimeCall, RuntimeEvent, RuntimeError, RuntimeOrigin, RuntimeFreezeReason, RuntimeHoldReason, RuntimeSlashReason, RuntimeLockId, RuntimeTask, RuntimeViewFunction )] pub struct Runtime; #[runtime::pezpallet_index(0)] pub type System = pezframe_system + Call + Event; #[runtime::pezpallet_index(1)] pub type Example = pezpallet; #[runtime::pezpallet_index(2)] #[runtime::disable_call] pub type Example2 = pallet2; #[cfg(feature = "frame-feature-testing")] #[runtime::pezpallet_index(3)] pub type Example3 = pallet3; #[runtime::pezpallet_index(4)] pub type Example4 = pallet4; #[cfg(feature = "frame-feature-testing-2")] #[runtime::pezpallet_index(5)] pub type Example5 = pallet5; } // Test that the part `RuntimeCall` is excluded from Example2 and included in Example4. fn _ensure_call_is_correctly_excluded_and_included(call: RuntimeCall) { match call { RuntimeCall::System(_) | RuntimeCall::Example(_) | RuntimeCall::Example4(_) => (), } } fn maybe_docs(doc: Vec<&'static str>) -> Vec<&'static str> { if cfg!(feature = "no-metadata-docs") { vec![] } else { doc } } #[test] #[allow(deprecated)] fn transactional_works() { TestExternalities::default().execute_with(|| { pezframe_system::Pezpallet::::set_block_number(1); pezpallet::Call::::foo_storage_layer { foo: 0 } .dispatch_bypass_filter(None.into()) .err() .unwrap(); assert!(pezframe_system::Pezpallet::::events().is_empty()); pezpallet::Call::::foo_storage_layer { foo: 1 } .dispatch_bypass_filter(None.into()) .unwrap(); assert_eq!( pezframe_system::Pezpallet::::events() .iter() .map(|e| &e.event) .collect::>(), vec![&RuntimeEvent::Example(pezpallet::Event::Something(0))], ); }) } #[test] fn call_expand() { let call_foo = pezpallet::Call::::foo { foo: 3, bar: 0 }; assert_eq!( call_foo.get_dispatch_info(), DispatchInfo { call_weight: pezframe_support::weights::Weight::from_parts(3, 0), extension_weight: Default::default(), class: DispatchClass::Normal, pays_fee: Pays::Yes } ); assert_eq!(call_foo.get_call_name(), "foo"); #[cfg(not(feature = "frame-feature-testing"))] assert_eq!( pezpallet::Call::::get_call_names(), &[ "foo", "foo_storage_layer", "foo_index_out_of_order", "foo_no_post_info", "check_for_dispatch_context" ], ); #[cfg(feature = "frame-feature-testing")] assert_eq!( pezpallet::Call::::get_call_names(), &[ "foo", "foo_storage_layer", "foo_index_out_of_order", "foo_no_post_info", "check_for_dispatch_context", "foo_feature_test" ], ); assert_eq!(call_foo.get_call_index(), 0u8); #[cfg(not(feature = "frame-feature-testing"))] assert_eq!(pezpallet::Call::::get_call_indices(), &[0u8, 1u8, 4u8, 2u8, 3u8]); #[cfg(feature = "frame-feature-testing")] assert_eq!(pezpallet::Call::::get_call_indices(), &[0u8, 1u8, 4u8, 2u8, 3u8, 5u8]); } #[test] fn call_expand_index() { let call_foo = pezpallet::Call::::foo_index_out_of_order {}; assert_eq!(call_foo.get_call_index(), 4u8); #[cfg(not(feature = "frame-feature-testing"))] assert_eq!(pezpallet::Call::::get_call_indices(), &[0u8, 1u8, 4u8, 2u8, 3u8]); #[cfg(feature = "frame-feature-testing")] assert_eq!(pezpallet::Call::::get_call_indices(), &[0u8, 1u8, 4u8, 2u8, 3u8, 5u8]); } #[test] fn error_expand() { assert_eq!( format!("{:?}", pezpallet::Error::::InsufficientProposersBalance), String::from("InsufficientProposersBalance"), ); assert_eq!( <&'static str>::from(pezpallet::Error::::InsufficientProposersBalance), "InsufficientProposersBalance", ); assert_eq!( DispatchError::from(pezpallet::Error::::InsufficientProposersBalance), DispatchError::Module(ModuleError { index: 1, error: [0, 0, 0, 0], message: Some("InsufficientProposersBalance") }), ); assert_eq!( as PalletError>::MAX_ENCODED_SIZE, 3); #[cfg(feature = "frame-feature-testing")] assert_eq!(format!("{:?}", pezpallet::Error::::FeatureTest), String::from("FeatureTest"),); } #[test] fn instance_expand() { // Assert same type. let _: pezpallet::__InherentHiddenInstance = (); } #[test] fn inherent_expand() { use pezframe_support::inherent::InherentData; use pezsp_core::Hasher; use pezsp_runtime::{ traits::{BlakeTwo256, Block as _, Header}, Digest, }; let inherents = InherentData::new().create_extrinsics(); let expected = vec![UncheckedExtrinsic::new_bare(RuntimeCall::Example(pezpallet::Call::foo_no_post_info {}))]; assert_eq!(expected, inherents); let block = Block::new( Header::new( 1, BlakeTwo256::hash(b"test"), BlakeTwo256::hash(b"test"), BlakeTwo256::hash(b"test"), Digest::default(), ), vec![ UncheckedExtrinsic::new_bare(RuntimeCall::Example(pezpallet::Call::foo_no_post_info {})), UncheckedExtrinsic::new_bare(RuntimeCall::Example(pezpallet::Call::foo { foo: 1, bar: 0, })), ], ); assert!(InherentData::new().check_extrinsics(&block.into()).ok()); let block = Block::new( Header::new( 1, BlakeTwo256::hash(b"test"), BlakeTwo256::hash(b"test"), BlakeTwo256::hash(b"test"), Digest::default(), ), vec![ UncheckedExtrinsic::new_bare(RuntimeCall::Example(pezpallet::Call::foo_no_post_info {})), UncheckedExtrinsic::new_bare(RuntimeCall::Example(pezpallet::Call::foo { foo: 0, bar: 0, })), ], ); assert!(InherentData::new().check_extrinsics(&block.into()).fatal_error()); let block = Block::new( Header::new( 1, BlakeTwo256::hash(b"test"), BlakeTwo256::hash(b"test"), BlakeTwo256::hash(b"test"), Digest::default(), ), vec![UncheckedExtrinsic::new_bare(RuntimeCall::Example(pezpallet::Call::foo_storage_layer { foo: 0, }))], ); let mut inherent = InherentData::new(); inherent.put_data(*b"required", &true).unwrap(); assert!(inherent.check_extrinsics(&block.into()).fatal_error()); let block = Block::new( Header::new( 1, BlakeTwo256::hash(b"test"), BlakeTwo256::hash(b"test"), BlakeTwo256::hash(b"test"), Digest::default(), ), vec![UncheckedExtrinsic::new_signed( RuntimeCall::Example(pezpallet::Call::foo_no_post_info {}), 1, 1.into(), Default::default(), )], ); let mut inherent = InherentData::new(); inherent.put_data(*b"required", &true).unwrap(); assert!(inherent.check_extrinsics(&block.into()).fatal_error()); } #[test] fn validate_unsigned_expand() { use pezframe_support::pezpallet_prelude::{ InvalidTransaction, TransactionSource, TransactionValidityError, ValidTransaction, ValidateUnsigned, }; let call = pezpallet::Call::::foo_no_post_info {}; let validity = pezpallet::Pezpallet::validate_unsigned(TransactionSource::Local, &call).unwrap_err(); assert_eq!(validity, TransactionValidityError::Invalid(InvalidTransaction::Call)); let call = pezpallet::Call::::foo_storage_layer { foo: 0 }; let validity = pezpallet::Pezpallet::validate_unsigned(TransactionSource::External, &call).unwrap(); assert_eq!(validity, ValidTransaction::default()); } #[test] fn composite_expand() { use codec::Encode; let hold_reason: RuntimeHoldReason = pezpallet::HoldReason::Staking.into(); let hold_reason2: RuntimeHoldReason = pallet2::HoldReason::Governance.into(); let slash_reason: RuntimeSlashReason = pallet2::SlashReason::Equivocation.into(); assert_eq!(hold_reason, RuntimeHoldReason::Example(pezpallet::HoldReason::Staking)); assert_eq!(hold_reason2, RuntimeHoldReason::Example2(pallet2::HoldReason::Governance)); assert_eq!(slash_reason, RuntimeSlashReason::Example2(pallet2::SlashReason::Equivocation)); assert_eq!(hold_reason.encode(), [1, 0]); assert_eq!(hold_reason2.encode(), [2, 0]); assert_eq!(slash_reason.encode(), [2, 0]); } #[test] #[allow(deprecated)] fn pezpallet_expand_deposit_event() { TestExternalities::default().execute_with(|| { pezframe_system::Pezpallet::::set_block_number(1); pezpallet::Call::::foo { foo: 3, bar: 0 } .dispatch_bypass_filter(None.into()) .unwrap(); assert_eq!( pezframe_system::Pezpallet::::events()[0].event, RuntimeEvent::Example(pezpallet::Event::Something(3)), ); }) } #[test] fn pezpallet_new_call_variant() { pezpallet::Call::::new_call_variant_foo(3, 4); } #[test] #[allow(deprecated)] fn storage_expand() { use pezframe_support::{pezpallet_prelude::*, storage::StoragePrefixedMap}; fn twox_64_concat(d: &[u8]) -> Vec { let mut v = twox_64(d).to_vec(); v.extend_from_slice(d); v } fn blake2_128_concat(d: &[u8]) -> Vec { let mut v = blake2_128(d).to_vec(); v.extend_from_slice(d); v } TestExternalities::default().execute_with(|| { pezpallet::Value::::put(1); let k = [twox_128(b"Example"), twox_128(b"Value")].concat(); assert_eq!(unhashed::get::(&k), Some(1u32)); pezpallet::RenamedValue::::put(2); let k = [twox_128(b"Example"), twox_128(b"Value2")].concat(); assert_eq!(unhashed::get::(&k), Some(2)); pezpallet::Map::::insert(1, 2); let mut k = [twox_128(b"Example"), twox_128(b"Map")].concat(); k.extend(1u8.using_encoded(blake2_128_concat)); assert_eq!(unhashed::get::(&k), Some(2u16)); assert_eq!(&k[..32], &>::final_prefix()); pezpallet::Map2::::insert(1, 2); let mut k = [twox_128(b"Example"), twox_128(b"Map2")].concat(); k.extend(1u16.using_encoded(twox_64_concat)); assert_eq!(unhashed::get::(&k), Some(2u32)); assert_eq!(&k[..32], &>::final_prefix()); pezpallet::Map3::::insert(1, 2); let mut k = [twox_128(b"Example"), twox_128(b"Map3")].concat(); k.extend(1u32.using_encoded(blake2_128_concat)); assert_eq!(unhashed::get::(&k), Some(2u64)); assert_eq!(&k[..32], &>::final_prefix()); assert_eq!( pezpallet::Map3::::get(2), Err(pezpallet::Error::::NonExistentStorageValue), ); pezpallet::DoubleMap::::insert(&1, &2, &3); let mut k = [twox_128(b"Example"), twox_128(b"DoubleMap")].concat(); k.extend(1u8.using_encoded(blake2_128_concat)); k.extend(2u16.using_encoded(twox_64_concat)); assert_eq!(unhashed::get::(&k), Some(3u32)); assert_eq!(&k[..32], &>::final_prefix()); pezpallet::DoubleMap2::::insert(&1, &2, &3); let mut k = [twox_128(b"Example"), twox_128(b"DoubleMap2")].concat(); k.extend(1u16.using_encoded(twox_64_concat)); k.extend(2u32.using_encoded(blake2_128_concat)); assert_eq!(unhashed::get::(&k), Some(3u64)); assert_eq!(&k[..32], &>::final_prefix()); pezpallet::DoubleMap3::::insert(&1, &2, &3); let mut k = [twox_128(b"Example"), twox_128(b"DoubleMap3")].concat(); k.extend(1u32.using_encoded(blake2_128_concat)); k.extend(2u64.using_encoded(twox_64_concat)); assert_eq!(unhashed::get::(&k), Some(3u128)); assert_eq!(&k[..32], &>::final_prefix()); assert_eq!( pezpallet::DoubleMap3::::get(2, 3), Err(pezpallet::Error::::NonExistentStorageValue), ); pezpallet::NMap::::insert((&1,), &3); let mut k = [twox_128(b"Example"), twox_128(b"NMap")].concat(); k.extend(1u8.using_encoded(blake2_128_concat)); assert_eq!(unhashed::get::(&k), Some(3u32)); assert_eq!(&k[..32], &>::final_prefix()); pezpallet::NMap2::::insert((&1, &2), &3); let mut k = [twox_128(b"Example"), twox_128(b"NMap2")].concat(); k.extend(1u16.using_encoded(twox_64_concat)); k.extend(2u32.using_encoded(blake2_128_concat)); assert_eq!(unhashed::get::(&k), Some(3u64)); assert_eq!(&k[..32], &>::final_prefix()); assert_eq!(pezpallet::Pezpallet::::nmap2((1, 2)), Some(3u64)); pezpallet::NMap3::::insert((&1, &2), &3); let mut k = [twox_128(b"Example"), twox_128(b"NMap3")].concat(); k.extend(1u8.using_encoded(blake2_128_concat)); k.extend(2u16.using_encoded(twox_64_concat)); assert_eq!(unhashed::get::(&k), Some(3u128)); assert_eq!(&k[..32], &>::final_prefix()); assert_eq!(pezpallet::Pezpallet::::nmap3((1, 2)), Ok(3u128)); assert_eq!( pezpallet::NMap3::::get((2, 3)), Err(pezpallet::Error::::NonExistentStorageValue), ); pezpallet::CountedNMap::::insert((&1,), &3); let mut k = [twox_128(b"Example"), twox_128(b"CountedNMap")].concat(); k.extend(1u8.using_encoded(blake2_128_concat)); assert_eq!(unhashed::get::(&k), Some(3u32)); assert_eq!(pezpallet::CountedNMap::::count(), 1); assert_eq!( unhashed::get::( &[twox_128(b"Example"), twox_128(b"CounterForCountedNMap")].concat() ), Some(1u32) ); pezpallet::CountedNMap2::::insert((&1, &2), &3); let mut k = [twox_128(b"Example"), twox_128(b"CountedNMap2")].concat(); k.extend(1u16.using_encoded(twox_64_concat)); k.extend(2u32.using_encoded(blake2_128_concat)); assert_eq!(unhashed::get::(&k), Some(3u64)); assert_eq!(pezpallet::CountedNMap2::::count(), 1); assert_eq!( unhashed::get::( &[twox_128(b"Example"), twox_128(b"CounterForCountedNMap2")].concat() ), Some(1u32) ); assert_eq!(pezpallet::Pezpallet::::counted_nmap2((1, 2)), Some(3u64)); pezpallet::CountedNMap3::::insert((&1, &2), &3); let mut k = [twox_128(b"Example"), twox_128(b"CountedNMap3")].concat(); k.extend(1u8.using_encoded(blake2_128_concat)); k.extend(2u16.using_encoded(twox_64_concat)); assert_eq!(pezpallet::CountedNMap3::::count(), 1); assert_eq!(unhashed::get::(&k), Some(3u128)); assert_eq!(pezpallet::Pezpallet::::counted_nmap3((1, 2)), Ok(3u128)); assert_eq!( pezpallet::CountedNMap3::::get((2, 3)), Err(pezpallet::Error::::NonExistentStorageValue), ); assert_eq!( unhashed::get::( &[twox_128(b"Example"), twox_128(b"CounterForCountedNMap3")].concat() ), Some(1u32) ); #[cfg(feature = "frame-feature-testing")] { pezpallet::ConditionalValue::::put(1); pezpallet::ConditionalMap::::insert(1, 2); pezpallet::ConditionalDoubleMap::::insert(1, 2, 3); pezpallet::ConditionalNMap::::insert((1, 2), 3); } pezpallet::SomeCountedStorageMap::::insert(1, 2); let mut k = [twox_128(b"Example"), twox_128(b"RenamedCountedMap")].concat(); k.extend(1u8.using_encoded(twox_64_concat)); assert_eq!(unhashed::get::(&k), Some(2u32)); let k = [twox_128(b"Example"), twox_128(b"CounterForRenamedCountedMap")].concat(); assert_eq!(unhashed::get::(&k), Some(1u32)); pezpallet::Unbounded::::put(vec![1, 2]); let k = [twox_128(b"Example"), twox_128(b"Unbounded")].concat(); assert_eq!(unhashed::get::>(&k), Some(vec![1, 2])); }) } #[test] #[allow(deprecated)] fn pezpallet_hooks_expand() { TestExternalities::default().execute_with(|| { pezframe_system::Pezpallet::::set_block_number(1); assert_eq!(AllPalletsWithoutSystem::on_initialize(1), Weight::from_parts(10, 0)); AllPalletsWithoutSystem::on_finalize(1); assert_eq!(AllPalletsWithoutSystem::on_runtime_upgrade(), Weight::from_parts(30, 0)); assert_eq!( pezframe_system::Pezpallet::::events()[0].event, RuntimeEvent::Example(pezpallet::Event::Something(10)), ); assert_eq!( pezframe_system::Pezpallet::::events()[1].event, RuntimeEvent::Example2(pallet2::Event::Something(11)), ); assert_eq!( pezframe_system::Pezpallet::::events()[2].event, RuntimeEvent::Example(pezpallet::Event::Something(20)), ); assert_eq!( pezframe_system::Pezpallet::::events()[3].event, RuntimeEvent::Example2(pallet2::Event::Something(21)), ); assert_eq!( pezframe_system::Pezpallet::::events()[4].event, RuntimeEvent::Example(pezpallet::Event::Something(30)), ); assert_eq!( pezframe_system::Pezpallet::::events()[5].event, RuntimeEvent::Example2(pallet2::Event::Something(31)), ); }) } #[test] fn pezpallet_on_genesis() { TestExternalities::default().execute_with(|| { assert_eq!(pezpallet::Pezpallet::::on_chain_storage_version(), StorageVersion::new(0)); pezpallet::Pezpallet::::on_genesis(); assert_eq!( pezpallet::Pezpallet::::in_code_storage_version(), pezpallet::Pezpallet::::on_chain_storage_version(), ); }) } #[test] fn migrate_from_pallet_version_to_storage_version() { const PALLET_VERSION_STORAGE_KEY_POSTFIX: &[u8] = b":__PALLET_VERSION__:"; fn pezpallet_version_key(name: &str) -> [u8; 32] { pezframe_support::storage::storage_prefix(name.as_bytes(), PALLET_VERSION_STORAGE_KEY_POSTFIX) } TestExternalities::default().execute_with(|| { // Insert some fake pezpallet versions pezsp_io::storage::set(&pezpallet_version_key(Example::name()), &[1, 2, 3]); pezsp_io::storage::set(&pezpallet_version_key(Example2::name()), &[1, 2, 3]); pezsp_io::storage::set(&pezpallet_version_key(System::name()), &[1, 2, 3]); // Check that everyone currently is at version 0 assert_eq!(Example::on_chain_storage_version(), StorageVersion::new(0)); assert_eq!(Example2::on_chain_storage_version(), StorageVersion::new(0)); assert_eq!(System::on_chain_storage_version(), StorageVersion::new(0)); let db_weight = RuntimeDbWeight { read: 0, write: 5 }; let weight = pezframe_support::migrations::migrate_from_pallet_version_to_storage_version::< AllPalletsWithSystem, >(&db_weight); let mut pezpallet_num = 4; if cfg!(feature = "frame-feature-testing") { pezpallet_num += 1; }; if cfg!(feature = "frame-feature-testing-2") { pezpallet_num += 1; }; // `pezpallet_num` pallets, 2 writes and every write costs 5 weight. assert_eq!(Weight::from_parts(pezpallet_num * 2 * 5, 0), weight); // All pezpallet versions should be removed assert!(pezsp_io::storage::get(&pezpallet_version_key(Example::name())).is_none()); assert!(pezsp_io::storage::get(&pezpallet_version_key(Example2::name())).is_none()); assert!(pezsp_io::storage::get(&pezpallet_version_key(System::name())).is_none()); assert_eq!(Example::on_chain_storage_version(), pezpallet::STORAGE_VERSION); assert_eq!(Example2::on_chain_storage_version(), pallet2::STORAGE_VERSION); assert_eq!(System::on_chain_storage_version(), StorageVersion::new(0)); }); } #[test] #[allow(deprecated)] fn pezpallet_item_docs_in_metadata() { // call let call_variants = match meta_type::>().type_info().type_def { scale_info::TypeDef::Variant(variants) => variants.variants, _ => unreachable!(), }; assert_eq!(call_variants[0].docs, maybe_docs(vec!["call foo doc comment put in metadata"])); assert_eq!( call_variants[1].docs, maybe_docs(vec!["call foo_storage_layer doc comment put in metadata"]) ); assert!(call_variants[2].docs.is_empty()); // event let event_variants = match meta_type::>().type_info().type_def { scale_info::TypeDef::Variant(variants) => variants.variants, _ => unreachable!(), }; assert_eq!(event_variants[0].docs, maybe_docs(vec!["event doc comment put in metadata"])); assert!(event_variants[1].docs.is_empty()); // error let error_variants = match meta_type::>().type_info().type_def { scale_info::TypeDef::Variant(variants) => variants.variants, _ => unreachable!(), }; assert_eq!(error_variants[0].docs, maybe_docs(vec!["error doc comment put in metadata"])); assert!(error_variants[1].docs.is_empty()); // storage is already covered in the main `fn metadata` test. } #[test] #[allow(deprecated)] fn metadata_v15() { use codec::Decode; use frame_metadata::{v15::*, *}; let readme = "Very important information :D\n"; let pezpallet_doc = "This is the best pezpallet\n"; let expected_pallet_doc = vec![" Pezpallet documentation", readme, pezpallet_doc]; let pallets = vec![ PalletMetadata { index: 1, name: "Example", storage: Some(PalletStorageMetadata { prefix: "Example", entries: vec![ StorageEntryMetadata { name: "ValueWhereClause", modifier: StorageEntryModifier::Optional, ty: StorageEntryType::Plain(meta_type::()), default: vec![0], docs: vec![], }, StorageEntryMetadata { name: "Value", modifier: StorageEntryModifier::Optional, ty: StorageEntryType::Plain(meta_type::()), default: vec![0], docs: vec![], }, StorageEntryMetadata { name: "Value2", modifier: StorageEntryModifier::Optional, ty: StorageEntryType::Plain(meta_type::()), default: vec![0], docs: vec![], }, StorageEntryMetadata { name: "Map", modifier: StorageEntryModifier::Default, ty: StorageEntryType::Map { key: meta_type::(), value: meta_type::(), hashers: vec![StorageHasher::Blake2_128Concat], }, default: vec![4, 0], docs: vec![], }, StorageEntryMetadata { name: "Map2", modifier: StorageEntryModifier::Optional, ty: StorageEntryType::Map { key: meta_type::(), value: meta_type::(), hashers: vec![StorageHasher::Twox64Concat], }, default: vec![0], docs: vec![], }, StorageEntryMetadata { name: "Map3", modifier: StorageEntryModifier::Optional, ty: StorageEntryType::Map { key: meta_type::(), value: meta_type::(), hashers: vec![StorageHasher::Blake2_128Concat], }, default: vec![1, 1], docs: vec![], }, StorageEntryMetadata { name: "DoubleMap", modifier: StorageEntryModifier::Optional, ty: StorageEntryType::Map { value: meta_type::(), hashers: vec![ StorageHasher::Blake2_128Concat, StorageHasher::Twox64Concat, ], key: meta_type::<(u8, u16)>(), }, default: vec![0], docs: vec![], }, StorageEntryMetadata { name: "DoubleMap2", modifier: StorageEntryModifier::Optional, ty: StorageEntryType::Map { value: meta_type::(), key: meta_type::<(u16, u32)>(), hashers: vec![ StorageHasher::Twox64Concat, StorageHasher::Blake2_128Concat, ], }, default: vec![0], docs: vec![], }, StorageEntryMetadata { name: "DoubleMap3", modifier: StorageEntryModifier::Optional, ty: StorageEntryType::Map { value: meta_type::(), key: meta_type::<(u32, u64)>(), hashers: vec![ StorageHasher::Blake2_128Concat, StorageHasher::Twox64Concat, ], }, default: vec![1, 1], docs: vec![], }, StorageEntryMetadata { name: "NMap", modifier: StorageEntryModifier::Optional, ty: StorageEntryType::Map { key: meta_type::(), hashers: vec![StorageHasher::Blake2_128Concat], value: meta_type::(), }, default: vec![0], docs: vec![], }, StorageEntryMetadata { name: "NMap2", modifier: StorageEntryModifier::Optional, ty: StorageEntryType::Map { key: meta_type::<(u16, u32)>(), hashers: vec![ StorageHasher::Twox64Concat, StorageHasher::Blake2_128Concat, ], value: meta_type::(), }, default: vec![0], docs: vec![], }, StorageEntryMetadata { name: "NMap3", modifier: StorageEntryModifier::Optional, ty: StorageEntryType::Map { key: meta_type::<(u8, u16)>(), hashers: vec![ StorageHasher::Blake2_128Concat, StorageHasher::Twox64Concat, ], value: meta_type::(), }, default: vec![1, 1], docs: vec![], }, StorageEntryMetadata { name: "CountedNMap", modifier: StorageEntryModifier::Optional, ty: StorageEntryType::Map { key: meta_type::(), hashers: vec![StorageHasher::Blake2_128Concat], value: meta_type::(), }, default: vec![0], docs: vec![], }, StorageEntryMetadata { name: "CounterForCountedNMap", modifier: StorageEntryModifier::Default, ty: StorageEntryType::Plain(meta_type::()), default: vec![0, 0, 0, 0], docs: maybe_docs(vec!["Counter for the related counted storage map"]), }, StorageEntryMetadata { name: "CountedNMap2", modifier: StorageEntryModifier::Optional, ty: StorageEntryType::Map { key: meta_type::<(u16, u32)>(), hashers: vec![ StorageHasher::Twox64Concat, StorageHasher::Blake2_128Concat, ], value: meta_type::(), }, default: vec![0], docs: vec![], }, StorageEntryMetadata { name: "CounterForCountedNMap2", modifier: StorageEntryModifier::Default, ty: StorageEntryType::Plain(meta_type::()), default: vec![0, 0, 0, 0], docs: maybe_docs(vec!["Counter for the related counted storage map"]), }, StorageEntryMetadata { name: "CountedNMap3", modifier: StorageEntryModifier::Optional, ty: StorageEntryType::Map { key: meta_type::<(u8, u16)>(), hashers: vec![ StorageHasher::Blake2_128Concat, StorageHasher::Twox64Concat, ], value: meta_type::(), }, default: vec![1, 1], docs: vec![], }, StorageEntryMetadata { name: "CounterForCountedNMap3", modifier: StorageEntryModifier::Default, ty: StorageEntryType::Plain(meta_type::()), default: vec![0, 0, 0, 0], docs: maybe_docs(vec!["Counter for the related counted storage map"]), }, #[cfg(feature = "frame-feature-testing")] StorageEntryMetadata { name: "ConditionalValue", modifier: StorageEntryModifier::Optional, ty: StorageEntryType::Plain(meta_type::()), default: vec![0], docs: vec![], }, #[cfg(feature = "frame-feature-testing")] StorageEntryMetadata { name: "ConditionalMap", modifier: StorageEntryModifier::Optional, ty: StorageEntryType::Map { key: meta_type::(), value: meta_type::(), hashers: vec![StorageHasher::Twox64Concat], }, default: vec![0], docs: vec![], }, #[cfg(feature = "frame-feature-testing")] StorageEntryMetadata { name: "ConditionalDoubleMap", modifier: StorageEntryModifier::Optional, ty: StorageEntryType::Map { value: meta_type::(), key: meta_type::<(u8, u16)>(), hashers: vec![ StorageHasher::Blake2_128Concat, StorageHasher::Twox64Concat, ], }, default: vec![0], docs: vec![], }, #[cfg(feature = "frame-feature-testing")] StorageEntryMetadata { name: "ConditionalNMap", modifier: StorageEntryModifier::Optional, ty: StorageEntryType::Map { key: meta_type::<(u8, u16)>(), hashers: vec![ StorageHasher::Blake2_128Concat, StorageHasher::Twox64Concat, ], value: meta_type::(), }, default: vec![0], docs: vec![], }, #[cfg(feature = "frame-feature-testing")] StorageEntryMetadata { name: "ConditionalCountedNMap", modifier: StorageEntryModifier::Optional, ty: StorageEntryType::Map { key: meta_type::<(u8, u16)>(), hashers: vec![ StorageHasher::Blake2_128Concat, StorageHasher::Twox64Concat, ], value: meta_type::(), }, default: vec![0], docs: vec![], }, #[cfg(feature = "frame-feature-testing")] StorageEntryMetadata { name: "CounterForConditionalCountedNMap", modifier: StorageEntryModifier::Default, ty: StorageEntryType::Plain(meta_type::()), default: vec![0, 0, 0, 0], docs: maybe_docs(vec!["Counter for the related counted storage map"]), }, StorageEntryMetadata { name: "RenamedCountedMap", modifier: StorageEntryModifier::Optional, ty: StorageEntryType::Map { hashers: vec![StorageHasher::Twox64Concat], key: meta_type::(), value: meta_type::(), }, default: vec![0], docs: vec![], }, StorageEntryMetadata { name: "CounterForRenamedCountedMap", modifier: StorageEntryModifier::Default, ty: StorageEntryType::Plain(meta_type::()), default: vec![0, 0, 0, 0], docs: maybe_docs(vec!["Counter for the related counted storage map"]), }, StorageEntryMetadata { name: "Unbounded", modifier: StorageEntryModifier::Optional, ty: StorageEntryType::Plain(meta_type::>()), default: vec![0], docs: vec![], }, ], }), calls: Some(meta_type::>().into()), event: Some(meta_type::>().into()), constants: vec![ PalletConstantMetadata { name: "MyGetParam", ty: meta_type::(), value: vec![10, 0, 0, 0], docs: maybe_docs(vec![" Some comment", " Some comment"]), }, PalletConstantMetadata { name: "MyGetParam2", ty: meta_type::(), value: vec![11, 0, 0, 0], docs: maybe_docs(vec![" Some comment", " Some comment"]), }, PalletConstantMetadata { name: "MyGetParam3", ty: meta_type::(), value: vec![12, 0, 0, 0, 0, 0, 0, 0], docs: vec![], }, PalletConstantMetadata { name: "some_extra", ty: meta_type::(), value: vec![100, 0, 0, 0, 0, 0, 0, 0], docs: maybe_docs(vec![" Some doc", " Some doc"]), }, PalletConstantMetadata { name: "some_extra_extra", ty: meta_type::(), value: vec![0, 0, 0, 0, 0, 0, 0, 0], docs: maybe_docs(vec![" Some doc"]), }, PalletConstantMetadata { name: "SomeExtraRename", ty: meta_type::(), value: vec![0, 0, 0, 0, 0, 0, 0, 0], docs: maybe_docs(vec![" Some doc"]), }, ], error: Some(PalletErrorMetadata { ty: meta_type::>() }), docs: expected_pallet_doc, }, PalletMetadata { index: 2, name: "Example2", storage: Some(PalletStorageMetadata { prefix: "Example2", entries: vec![ StorageEntryMetadata { name: "SomeValue", modifier: StorageEntryModifier::Optional, ty: StorageEntryType::Plain(meta_type::>()), default: vec![0], docs: vec![], }, StorageEntryMetadata { name: "SomeCountedStorageMap", modifier: StorageEntryModifier::Optional, ty: StorageEntryType::Map { hashers: vec![StorageHasher::Twox64Concat], key: meta_type::(), value: meta_type::(), }, default: vec![0], docs: vec![], }, StorageEntryMetadata { name: "CounterForSomeCountedStorageMap", modifier: StorageEntryModifier::Default, ty: StorageEntryType::Plain(meta_type::()), default: vec![0, 0, 0, 0], docs: maybe_docs(vec!["Counter for the related counted storage map"]), }, ], }), calls: None, event: Some(PalletEventMetadata { ty: meta_type::() }), constants: vec![], error: None, docs: vec![], }, #[cfg(feature = "frame-feature-testing")] PalletMetadata { index: 3, name: "Example3", storage: None, calls: None, event: None, constants: vec![], error: None, docs: vec![" Test that the supertrait check works when we pass some parameter to the `pezframe_system::Config`."], }, PalletMetadata { index: 4, name: "Example4", storage: None, calls: Some(meta_type::>().into()), event: None, constants: vec![], error: None, docs: vec![], }, #[cfg(feature = "frame-feature-testing-2")] PalletMetadata { index: 5, name: "Example5", storage: None, calls: None, event: None, constants: vec![], error: None, docs: vec![" Test that the supertrait check works when we pass some parameter to the `pezframe_system::Config`."], }, ]; let empty_doc = pallets[0].event.as_ref().unwrap().ty.type_info().docs.is_empty() && pallets[0].error.as_ref().unwrap().ty.type_info().docs.is_empty() && pallets[0].calls.as_ref().unwrap().ty.type_info().docs.is_empty(); if cfg!(feature = "no-metadata-docs") { assert!(empty_doc) } else { assert!(!empty_doc) } let extrinsic = ExtrinsicMetadata { version: 5, signed_extensions: vec![SignedExtensionMetadata { identifier: "UnitSignedExtension", ty: meta_type::<()>(), additional_signed: meta_type::<()>(), }], address_ty: meta_type::< <<::Block as BlockT>::Extrinsic as SignedTransactionBuilder>::Address >(), call_ty: meta_type::<>::RuntimeCall>(), signature_ty: meta_type::< <<::Block as BlockT>::Extrinsic as SignedTransactionBuilder>::Signature >(), extra_ty: meta_type::< <<::Block as BlockT>::Extrinsic as SignedTransactionBuilder>::Extension >(), }; let outer_enums = OuterEnums { call_enum_ty: meta_type::(), event_enum_ty: meta_type::(), error_enum_ty: meta_type::(), }; let expected_metadata: RuntimeMetadataPrefixed = RuntimeMetadataLastVersion::new( pallets, extrinsic, meta_type::(), vec![], outer_enums, CustomMetadata { map: Default::default() }, ) .into(); let expected_metadata = match expected_metadata.1 { RuntimeMetadata::V15(metadata) => metadata, _ => panic!("metadata has been bumped, test needs to be updated"), }; let bytes = &Runtime::metadata_at_version(15).expect("Metadata must be present; qed"); let actual_metadata: RuntimeMetadataPrefixed = Decode::decode(&mut &bytes[..]).expect("Metadata encoded properly; qed"); let actual_metadata = match actual_metadata.1 { RuntimeMetadata::V15(metadata) => metadata, _ => panic!("metadata has been bumped, test needs to be updated"), }; pretty_assertions::assert_eq!(actual_metadata.pallets, expected_metadata.pallets); } #[test] fn metadata_at_version() { use frame_metadata::*; use pezsp_core::Decode; // Metadata always returns the V14.3 let metadata = Runtime::metadata(); let at_metadata = match Runtime::metadata_at_version(14) { Some(opaque) => { let bytes = &*opaque; let metadata: RuntimeMetadataPrefixed = Decode::decode(&mut &bytes[..]).unwrap(); metadata }, _ => panic!("metadata has been bumped, test needs to be updated"), }; assert_eq!(metadata, at_metadata); } #[test] fn metadata_versions() { assert_eq!(vec![14, 15, 16], Runtime::metadata_versions()); } #[test] fn metadata_ir_pallet_runtime_docs() { let ir = Runtime::metadata_ir(); let pezpallet = ir .pallets .iter() .find(|pezpallet| pezpallet.name == "Example") .expect("Pezpallet should be present"); let readme = "Very important information :D\n"; let pezpallet_doc = "This is the best pezpallet\n"; let expected = vec![" Pezpallet documentation", readme, pezpallet_doc]; assert_eq!(pezpallet.docs, expected); } #[test] fn extrinsic_metadata_ir_types() { let ir = Runtime::metadata_ir().extrinsic; assert_eq!( meta_type::<<<::Block as BlockT>::Extrinsic as SignedTransactionBuilder>::Address>(), ir.address_ty ); assert_eq!(meta_type::(), ir.address_ty); assert_eq!( meta_type::<>::RuntimeCall>(), ir.call_ty ); assert_eq!(meta_type::(), ir.call_ty); assert_eq!( meta_type::<<<::Block as BlockT>::Extrinsic as SignedTransactionBuilder>::Signature>(), ir.signature_ty ); assert_eq!(meta_type::(), ir.signature_ty); assert_eq!( meta_type::<<<::Block as BlockT>::Extrinsic as SignedTransactionBuilder>::Extension>(), ir.extra_ty ); assert_eq!(meta_type::>(), ir.extra_ty); } #[test] fn test_pallet_runtime_docs() { let docs = crate::pezpallet::Pezpallet::::pezpallet_documentation_metadata(); let readme = "Very important information :D\n"; let pezpallet_doc = "This is the best pezpallet\n"; let expected = vec![" Pezpallet documentation", readme, pezpallet_doc]; assert_eq!(docs, expected); } #[test] fn test_pallet_info_access() { assert_eq!(::name(), "System"); assert_eq!(::name(), "Example"); assert_eq!(::name(), "Example2"); assert_eq!(::index(), 0); assert_eq!(::index(), 1); assert_eq!(::index(), 2); } #[test] fn test_storage_info() { use pezframe_support::{ storage::storage_prefix as prefix, traits::{StorageInfo, StorageInfoTrait}, }; // Storage max size is calculated by adding up all the hasher size, the key type size and the // value type size assert_eq!( Example::storage_info(), vec![ StorageInfo { pezpallet_name: b"Example".to_vec(), storage_name: b"ValueWhereClause".to_vec(), prefix: prefix(b"Example", b"ValueWhereClause").to_vec(), max_values: Some(1), max_size: Some(8), }, StorageInfo { pezpallet_name: b"Example".to_vec(), storage_name: b"Value".to_vec(), prefix: prefix(b"Example", b"Value").to_vec(), max_values: Some(1), max_size: Some(4), }, StorageInfo { pezpallet_name: b"Example".to_vec(), storage_name: b"Value2".to_vec(), prefix: prefix(b"Example", b"Value2").to_vec(), max_values: Some(1), max_size: Some(8), }, StorageInfo { pezpallet_name: b"Example".to_vec(), storage_name: b"Map".to_vec(), prefix: prefix(b"Example", b"Map").to_vec(), max_values: None, max_size: Some(16 + 1 + 2), }, StorageInfo { pezpallet_name: b"Example".to_vec(), storage_name: b"Map2".to_vec(), prefix: prefix(b"Example", b"Map2").to_vec(), max_values: Some(3), max_size: Some(8 + 2 + 4), }, StorageInfo { pezpallet_name: b"Example".to_vec(), storage_name: b"Map3".to_vec(), prefix: prefix(b"Example", b"Map3").to_vec(), max_values: None, max_size: Some(16 + 4 + 8), }, StorageInfo { pezpallet_name: b"Example".to_vec(), storage_name: b"DoubleMap".to_vec(), prefix: prefix(b"Example", b"DoubleMap").to_vec(), max_values: None, max_size: Some(16 + 1 + 8 + 2 + 4), }, StorageInfo { pezpallet_name: b"Example".to_vec(), storage_name: b"DoubleMap2".to_vec(), prefix: prefix(b"Example", b"DoubleMap2").to_vec(), max_values: Some(5), max_size: Some(8 + 2 + 16 + 4 + 8), }, StorageInfo { pezpallet_name: b"Example".to_vec(), storage_name: b"DoubleMap3".to_vec(), prefix: prefix(b"Example", b"DoubleMap3").to_vec(), max_values: None, max_size: Some(16 + 4 + 8 + 8 + 16), }, StorageInfo { pezpallet_name: b"Example".to_vec(), storage_name: b"NMap".to_vec(), prefix: prefix(b"Example", b"NMap").to_vec(), max_values: None, max_size: Some(16 + 1 + 4), }, StorageInfo { pezpallet_name: b"Example".to_vec(), storage_name: b"NMap2".to_vec(), prefix: prefix(b"Example", b"NMap2").to_vec(), max_values: Some(11), max_size: Some(8 + 2 + 16 + 4 + 8), }, StorageInfo { pezpallet_name: b"Example".to_vec(), storage_name: b"NMap3".to_vec(), prefix: prefix(b"Example", b"NMap3").to_vec(), max_values: None, max_size: Some(16 + 1 + 8 + 2 + 16), }, StorageInfo { pezpallet_name: b"Example".to_vec(), storage_name: b"CountedNMap".to_vec(), prefix: prefix(b"Example", b"CountedNMap").to_vec(), max_values: None, max_size: Some(16 + 1 + 4), }, StorageInfo { pezpallet_name: b"Example".to_vec(), storage_name: b"CounterForCountedNMap".to_vec(), prefix: prefix(b"Example", b"CounterForCountedNMap").to_vec(), max_values: Some(1), max_size: Some(4), }, StorageInfo { pezpallet_name: b"Example".to_vec(), storage_name: b"CountedNMap2".to_vec(), prefix: prefix(b"Example", b"CountedNMap2").to_vec(), max_values: Some(11), max_size: Some(8 + 2 + 16 + 4 + 8), }, StorageInfo { pezpallet_name: b"Example".to_vec(), storage_name: b"CounterForCountedNMap2".to_vec(), prefix: prefix(b"Example", b"CounterForCountedNMap2").to_vec(), max_values: Some(1), max_size: Some(4), }, StorageInfo { pezpallet_name: b"Example".to_vec(), storage_name: b"CountedNMap3".to_vec(), prefix: prefix(b"Example", b"CountedNMap3").to_vec(), max_values: None, max_size: Some(16 + 1 + 8 + 2 + 16), }, StorageInfo { pezpallet_name: b"Example".to_vec(), storage_name: b"CounterForCountedNMap3".to_vec(), prefix: prefix(b"Example", b"CounterForCountedNMap3").to_vec(), max_values: Some(1), max_size: Some(4), }, #[cfg(feature = "frame-feature-testing")] { StorageInfo { pezpallet_name: b"Example".to_vec(), storage_name: b"ConditionalValue".to_vec(), prefix: prefix(b"Example", b"ConditionalValue").to_vec(), max_values: Some(1), max_size: Some(4), } }, #[cfg(feature = "frame-feature-testing")] { StorageInfo { pezpallet_name: b"Example".to_vec(), storage_name: b"ConditionalMap".to_vec(), prefix: prefix(b"Example", b"ConditionalMap").to_vec(), max_values: Some(12), max_size: Some(8 + 2 + 4), } }, #[cfg(feature = "frame-feature-testing")] { StorageInfo { pezpallet_name: b"Example".to_vec(), storage_name: b"ConditionalDoubleMap".to_vec(), prefix: prefix(b"Example", b"ConditionalDoubleMap").to_vec(), max_values: None, max_size: Some(16 + 1 + 8 + 2 + 4), } }, #[cfg(feature = "frame-feature-testing")] { StorageInfo { pezpallet_name: b"Example".to_vec(), storage_name: b"ConditionalNMap".to_vec(), prefix: prefix(b"Example", b"ConditionalNMap").to_vec(), max_values: None, max_size: Some(16 + 1 + 8 + 2 + 4), } }, #[cfg(feature = "frame-feature-testing")] { StorageInfo { pezpallet_name: b"Example".to_vec(), storage_name: b"ConditionalCountedNMap".to_vec(), prefix: prefix(b"Example", b"ConditionalCountedNMap").to_vec(), max_values: None, max_size: Some(16 + 1 + 8 + 2 + 4), } }, #[cfg(feature = "frame-feature-testing")] { StorageInfo { pezpallet_name: b"Example".to_vec(), storage_name: b"CounterForConditionalCountedNMap".to_vec(), prefix: prefix(b"Example", b"CounterForConditionalCountedNMap").to_vec(), max_values: Some(1), max_size: Some(4), } }, StorageInfo { pezpallet_name: b"Example".to_vec(), storage_name: b"RenamedCountedMap".to_vec(), prefix: prefix(b"Example", b"RenamedCountedMap").to_vec(), max_values: None, max_size: Some(8 + 1 + 4), }, StorageInfo { pezpallet_name: b"Example".to_vec(), storage_name: b"CounterForRenamedCountedMap".to_vec(), prefix: prefix(b"Example", b"CounterForRenamedCountedMap").to_vec(), max_values: Some(1), max_size: Some(4), }, StorageInfo { pezpallet_name: b"Example".to_vec(), storage_name: b"Unbounded".to_vec(), prefix: prefix(b"Example", b"Unbounded").to_vec(), max_values: Some(1), max_size: None, }, ], ); assert_eq!( Example2::storage_info(), vec![ StorageInfo { pezpallet_name: b"Example2".to_vec(), storage_name: b"SomeValue".to_vec(), prefix: prefix(b"Example2", b"SomeValue").to_vec(), max_values: Some(1), max_size: None, }, StorageInfo { pezpallet_name: b"Example2".to_vec(), storage_name: b"SomeCountedStorageMap".to_vec(), prefix: prefix(b"Example2", b"SomeCountedStorageMap").to_vec(), max_values: None, max_size: None, }, StorageInfo { pezpallet_name: b"Example2".to_vec(), storage_name: b"CounterForSomeCountedStorageMap".to_vec(), prefix: prefix(b"Example2", b"CounterForSomeCountedStorageMap").to_vec(), max_values: Some(1), max_size: Some(4), }, ], ); } #[test] fn assert_type_all_pallets_with_system_is_correct() { // Just ensure the 2 types are same. fn _a(_t: AllPalletsWithSystem) {} #[cfg(all(not(feature = "frame-feature-testing"), not(feature = "frame-feature-testing-2")))] fn _b(t: (System, Example, Example2, Example4)) { _a(t) } #[cfg(all(feature = "frame-feature-testing", not(feature = "frame-feature-testing-2")))] fn _b(t: (System, Example, Example2, Example3, Example4)) { _a(t) } #[cfg(all(not(feature = "frame-feature-testing"), feature = "frame-feature-testing-2"))] fn _b(t: (System, Example, Example2, Example4, Example5)) { _a(t) } #[cfg(all(feature = "frame-feature-testing", feature = "frame-feature-testing-2"))] fn _b(t: (System, Example, Example2, Example3, Example4, Example5)) { _a(t) } } #[test] fn assert_type_all_pallets_without_system_is_correct() { // Just ensure the 2 types are same. fn _a(_t: AllPalletsWithoutSystem) {} #[cfg(all(not(feature = "frame-feature-testing"), not(feature = "frame-feature-testing-2")))] fn _b(t: (Example, Example2, Example4)) { _a(t) } #[cfg(all(feature = "frame-feature-testing", not(feature = "frame-feature-testing-2")))] fn _b(t: (Example, Example2, Example3, Example4)) { _a(t) } #[cfg(all(not(feature = "frame-feature-testing"), feature = "frame-feature-testing-2"))] fn _b(t: (Example, Example2, Example4, Example5)) { _a(t) } #[cfg(all(feature = "frame-feature-testing", feature = "frame-feature-testing-2"))] fn _b(t: (Example, Example2, Example3, Example4, Example5)) { _a(t) } } #[test] fn test_storage_alias() { use pezframe_support::Twox64Concat; #[pezframe_support::storage_alias] type Value where ::AccountId: From + SomeAssociation1, = StorageValue, u32, ValueQuery>; #[pezframe_support::storage_alias] type SomeCountedStorageMap where ::AccountId: From + SomeAssociation1, = CountedStorageMap, Twox64Concat, u8, u32>; TestExternalities::default().execute_with(|| { pezpallet::Value::::put(10); assert_eq!(10, Value::::get()); pallet2::SomeCountedStorageMap::::insert(10, 100); assert_eq!(Some(100), SomeCountedStorageMap::::get(10)); assert_eq!(1, SomeCountedStorageMap::::count()); assert_eq!( SomeCountedStorageMap::::storage_info(), pallet2::SomeCountedStorageMap::::storage_info() ); }) } #[test] fn pezpallet_on_chain_storage_version_initializes_correctly() { type Executive = pezframe_executive::Executive< Runtime, Block, pezframe_system::ChainContext, Runtime, AllPalletsWithSystem, >; // Simple example of a pezpallet with in-code version 10 being added to the runtime for the first // time. TestExternalities::default().execute_with(|| { let in_code_version = Example::in_code_storage_version(); // Check the pezpallet has no storage items set. let pezpallet_hashed_prefix = twox_128(Example::name().as_bytes()); let exists = contains_prefixed_key(&pezpallet_hashed_prefix); assert_eq!(exists, false); // [`pezframe_support::traits::BeforeAllRuntimeMigrations`] hook should initialize the storage // version. Executive::execute_on_runtime_upgrade(); // Check that the storage version was initialized to the in-code version let on_chain_version_after = StorageVersion::get::(); assert_eq!(on_chain_version_after, in_code_version); }); // Pezpallet with no in-code storage version should have the on-chain version initialized to 0. TestExternalities::default().execute_with(|| { // Example4 in_code_storage_version is NoStorageVersionSet. // Check the pezpallet has no storage items set. let pezpallet_hashed_prefix = twox_128(Example4::name().as_bytes()); let exists = contains_prefixed_key(&pezpallet_hashed_prefix); assert_eq!(exists, false); // Confirm the storage version is implicitly 0. let on_chain_version_before = StorageVersion::get::(); assert_eq!(on_chain_version_before, StorageVersion::new(0)); // [`pezframe_support::traits::BeforeAllRuntimeMigrations`] initializes the storage version. Executive::execute_on_runtime_upgrade(); // Check that the storage version now exists and was initialized to 0. let on_chain_version_after = StorageVersion::get::(); assert_eq!(StorageVersion::exists::(), true); assert_eq!(on_chain_version_after, StorageVersion::new(0)); }); } #[cfg(feature = "try-runtime")] #[test] fn post_runtime_upgrade_detects_storage_version_issues() { use pezframe_support::traits::UpgradeCheckSelect; struct CustomUpgrade; impl OnRuntimeUpgrade for CustomUpgrade { fn on_runtime_upgrade() -> Weight { Example2::in_code_storage_version().put::(); Default::default() } } struct CustomUpgradePallet4; impl OnRuntimeUpgrade for CustomUpgradePallet4 { fn on_runtime_upgrade() -> Weight { StorageVersion::new(100).put::(); Default::default() } } type Executive = pezframe_executive::Executive< Runtime, Block, pezframe_system::ChainContext, Runtime, AllPalletsWithSystem, >; /// TODO: The `OnRuntimeUpgrade` generic parameter in `Executive` is deprecated and will be /// removed in a future version. Once removed, this `#[allow(deprecated)]` attribute /// can be safely deleted. #[allow(deprecated)] type ExecutiveWithUpgrade = pezframe_executive::Executive< Runtime, Block, pezframe_system::ChainContext, Runtime, AllPalletsWithSystem, CustomUpgrade, >; /// TODO: The `OnRuntimeUpgrade` generic parameter in `Executive` is deprecated and will be /// removed in a future version. Once removed, this `#[allow(deprecated)]` attribute /// can be safely deleted. #[allow(deprecated)] type ExecutiveWithUpgradePallet4 = pezframe_executive::Executive< Runtime, Block, pezframe_system::ChainContext, Runtime, AllPalletsWithSystem, CustomUpgradePallet4, >; TestExternalities::default().execute_with(|| { // Set the on-chain version to one less than the in-code version for `Example`, simulating a // forgotten migration StorageVersion::new(9).put::(); // The version isn't changed, we should detect it. assert!( Executive::try_runtime_upgrade(UpgradeCheckSelect::PreAndPost).unwrap_err() == "On chain and in-code storage version do not match. Missing runtime upgrade?" .into() ); }); TestExternalities::default().execute_with(|| { // Call `on_genesis` to put the storage version of `Example` into the storage. Example::on_genesis(); // We set the new storage version in the pezpallet and that should be detected. UpdateStorageVersion::set(&true); Executive::try_runtime_upgrade(UpgradeCheckSelect::PreAndPost).unwrap(); }); TestExternalities::default().execute_with(|| { // Call `on_genesis` to put the storage version of `Example` into the storage. Example::on_genesis(); // We set the new storage version in the custom upgrade and that should be detected. ExecutiveWithUpgrade::try_runtime_upgrade(UpgradeCheckSelect::PreAndPost).unwrap(); }); TestExternalities::default().execute_with(|| { // Call `on_genesis` to put the storage version of `Example` into the storage. Example::on_genesis(); // We need to set the correct storage version for `Example2` UpdateStorageVersion::set(&true); // `CustomUpgradePallet4` will set a storage version for `Example4` while this doesn't has // any storage version "enabled". assert!( ExecutiveWithUpgradePallet4::try_runtime_upgrade(UpgradeCheckSelect::PreAndPost) .unwrap_err() == "On chain storage version set, while the pezpallet \ doesn't have the `#[pezpallet::storage_version(VERSION)]` attribute." .into() ); }); } #[test] fn test_dispatch_context() { TestExternalities::default().execute_with(|| { // By default there is no context assert!(with_context::<(), _>(|_| ()).is_none()); // When not using `dispatch`, there should be no dispatch context assert_eq!( DispatchError::Unavailable, Example::check_for_dispatch_context(RuntimeOrigin::root()).unwrap_err(), ); // When using `dispatch`, there should be a dispatch context assert_ok!(RuntimeCall::from(pezpallet::Call::::check_for_dispatch_context {}) .dispatch(RuntimeOrigin::root())); }); } #[test] fn test_call_feature_parsing() { let call = pezpallet::Call::::check_for_dispatch_context {}; match call { pezpallet::Call::::check_for_dispatch_context {} | pezpallet::Call::::foo { .. } | pezpallet::Call::foo_storage_layer { .. } | pezpallet::Call::foo_index_out_of_order {} | pezpallet::Call::foo_no_post_info {} => (), #[cfg(feature = "frame-feature-testing")] pezpallet::Call::foo_feature_test {} => (), pezpallet::Call::__Ignore(_, _) => (), } } #[test] #[allow(deprecated)] fn test_error_feature_parsing() { let err = pezpallet::Error::::InsufficientProposersBalance; match err { pezpallet::Error::InsufficientProposersBalance | pezpallet::Error::NonExistentStorageValue | pezpallet::Error::Code(_) | pezpallet::Error::Skipped(_) | pezpallet::Error::CompactU8(_) => (), #[cfg(feature = "frame-feature-testing")] pezpallet::Error::FeatureTest => (), pezpallet::Error::__Ignore(_, _) => (), } } #[test] fn pezpallet_metadata() { use pezsp_metadata_ir::{EnumDeprecationInfoIR, ItemDeprecationInfoIR, VariantDeprecationInfoIR}; let pallets = Runtime::metadata_ir().pallets; let example = pallets[0].clone(); let example2 = pallets[1].clone(); { // Example pezpallet calls is fully and partially deprecated let meta = &example.calls.unwrap(); assert_eq!( EnumDeprecationInfoIR(BTreeMap::from([( 0, VariantDeprecationInfoIR::Deprecated { note: "test", since: None } )])), meta.deprecation_info ) } { // Example pezpallet constant is deprecated let meta = &example.constants[0]; assert_eq!( ItemDeprecationInfoIR::Deprecated { note: "test 2", since: None }, meta.deprecation_info ) } { // Example pezpallet errors are partially and fully deprecated let meta = &example.error.unwrap(); assert_eq!( EnumDeprecationInfoIR(BTreeMap::from([( 2, VariantDeprecationInfoIR::Deprecated { note: "test", since: None } )])), meta.deprecation_info ) } { // Example pezpallet events are partially and fully deprecated let meta = example.event.unwrap(); assert_eq!( EnumDeprecationInfoIR(BTreeMap::from([( 1, VariantDeprecationInfoIR::Deprecated { note: "test", since: None } )])), meta.deprecation_info ); } { // Example2 pezpallet events are not deprecated let meta = example2.event.unwrap(); assert!(!meta.deprecation_info.has_deprecated_variants()); } }