base for testing new pallets

This commit is contained in:
Ozgun Ozerk
2023-11-09 16:03:00 +03:00
parent 0dd9bbcbe7
commit 897845d6f6
26 changed files with 17870 additions and 0 deletions
+20
View File
@@ -0,0 +1,20 @@
//! Benchmarking setup for pallet-parachain-template
use super::*;
#[allow(unused)]
use crate::Pallet as Template;
use frame_benchmarking::{benchmarks, impl_benchmark_test_suite, whitelisted_caller};
use frame_system::RawOrigin;
benchmarks! {
do_something {
let s in 0 .. 100;
let caller: T::AccountId = whitelisted_caller();
}: _(RawOrigin::Signed(caller), s)
verify {
assert_eq!(Something::<T>::get(), Some(s));
}
}
impl_benchmark_test_suite!(Template, crate::mock::new_test_ext(), crate::mock::Test,);
+106
View File
@@ -0,0 +1,106 @@
#![cfg_attr(not(feature = "std"), no_std)]
/// Edit this file to define custom logic or remove it if it is not needed.
/// Learn more about FRAME and the core library of Substrate FRAME pallets:
/// <https://docs.substrate.io/v3/runtime/frame>
pub use pallet::*;
#[cfg(test)]
mod mock;
#[cfg(test)]
mod tests;
#[cfg(feature = "runtime-benchmarks")]
mod benchmarking;
#[frame_support::pallet]
pub mod pallet {
use frame_support::{dispatch::DispatchResultWithPostInfo, pallet_prelude::*};
use frame_system::pallet_prelude::*;
/// Configure the pallet by specifying the parameters and types on which it depends.
#[pallet::config]
pub trait Config: frame_system::Config {
/// Because this pallet emits events, it depends on the runtime's definition of an event.
type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;
}
#[pallet::pallet]
pub struct Pallet<T>(_);
// The pallet's runtime storage items.
// https://docs.substrate.io/v3/runtime/storage
#[pallet::storage]
#[pallet::getter(fn something)]
// Learn more about declaring storage items:
// https://docs.substrate.io/v3/runtime/storage#declaring-storage-items
pub type Something<T> = StorageValue<_, u32>;
// Pallets use events to inform users when important changes are made.
// https://docs.substrate.io/v3/runtime/events-and-errors
#[pallet::event]
#[pallet::generate_deposit(pub(super) fn deposit_event)]
pub enum Event<T: Config> {
/// Event documentation should end with an array that provides descriptive names for event
/// parameters. [something, who]
SomethingStored(u32, T::AccountId),
}
// Errors inform users that something went wrong.
#[pallet::error]
pub enum Error<T> {
/// Error names should be descriptive.
NoneValue,
/// Errors should have helpful documentation associated with them.
StorageOverflow,
}
#[pallet::hooks]
impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {}
// Dispatchable functions allows users to interact with the pallet and invoke state changes.
// These functions materialize as "extrinsics", which are often compared to transactions.
// Dispatchable functions must be annotated with a weight and must return a DispatchResult.
#[pallet::call]
impl<T: Config> Pallet<T> {
/// An example dispatchable that takes a singles value as a parameter, writes the value to
/// storage and emits an event. This function must be dispatched by a signed extrinsic.
#[pallet::call_index(0)]
#[pallet::weight(Weight::from_parts(10_000, 0) + T::DbWeight::get().writes(1))]
pub fn do_something(origin: OriginFor<T>, something: u32) -> DispatchResultWithPostInfo {
// Check that the extrinsic was signed and get the signer.
// This function will return an error if the extrinsic is not signed.
// https://docs.substrate.io/v3/runtime/origins
let who = ensure_signed(origin)?;
// Update storage.
<Something<T>>::put(something);
// Emit an event.
Self::deposit_event(Event::SomethingStored(something, who));
// Return a successful DispatchResultWithPostInfo
Ok(().into())
}
/// An example dispatchable that may throw a custom error.
#[pallet::call_index(1)]
#[pallet::weight(Weight::from_parts(10_000, 0) + T::DbWeight::get().reads_writes(1,1))]
pub fn cause_error(origin: OriginFor<T>) -> DispatchResultWithPostInfo {
let _who = ensure_signed(origin)?;
// Read a value from storage.
match <Something<T>>::get() {
// Return an error if the value has not been set.
None => Err(Error::<T>::NoneValue)?,
Some(old) => {
// Increment the value read from storage; will error in the event of overflow.
let new = old.checked_add(1).ok_or(Error::<T>::StorageOverflow)?;
// Update the value in storage with the incremented result.
<Something<T>>::put(new);
Ok(().into())
},
}
}
}
}
+58
View File
@@ -0,0 +1,58 @@
use frame_support::{parameter_types, traits::Everything};
use frame_system as system;
use sp_core::H256;
use sp_runtime::{
traits::{BlakeTwo256, IdentityLookup},
BuildStorage,
};
type Block = frame_system::mocking::MockBlock<Test>;
// Configure a mock runtime to test the pallet.
frame_support::construct_runtime!(
pub enum Test
{
System: frame_system::{Pallet, Call, Config<T>, Storage, Event<T>},
TemplateModule: crate::{Pallet, Call, Storage, Event<T>},
}
);
parameter_types! {
pub const BlockHashCount: u64 = 250;
pub const SS58Prefix: u8 = 42;
}
impl system::Config for Test {
type BaseCallFilter = Everything;
type BlockWeights = ();
type BlockLength = ();
type DbWeight = ();
type RuntimeOrigin = RuntimeOrigin;
type RuntimeCall = RuntimeCall;
type Nonce = u64;
type Hash = H256;
type Hashing = BlakeTwo256;
type AccountId = u64;
type Lookup = IdentityLookup<Self::AccountId>;
type Block = Block;
type RuntimeEvent = RuntimeEvent;
type BlockHashCount = BlockHashCount;
type Version = ();
type PalletInfo = PalletInfo;
type AccountData = ();
type OnNewAccount = ();
type OnKilledAccount = ();
type SystemWeightInfo = ();
type SS58Prefix = SS58Prefix;
type OnSetCode = ();
type MaxConsumers = frame_support::traits::ConstU32<16>;
}
impl crate::Config for Test {
type RuntimeEvent = RuntimeEvent;
}
// Build genesis storage according to the mock runtime.
pub fn new_test_ext() -> sp_io::TestExternalities {
system::GenesisConfig::<Test>::default().build_storage().unwrap().into()
}
+23
View File
@@ -0,0 +1,23 @@
use crate::{mock::*, Error};
use frame_support::{assert_noop, assert_ok};
#[test]
fn it_works_for_default_value() {
new_test_ext().execute_with(|| {
// Dispatch a signed extrinsic.
assert_ok!(TemplateModule::do_something(RuntimeOrigin::signed(1), 42));
// Read pallet storage and assert an expected result.
assert_eq!(TemplateModule::something(), Some(42));
});
}
#[test]
fn correct_error_for_none_value() {
new_test_ext().execute_with(|| {
// Ensure the expected error is thrown when no value is present.
assert_noop!(
TemplateModule::cause_error(RuntimeOrigin::signed(1)),
Error::<Test>::NoneValue
);
});
}