Benchmarking pallet-example (#8301)

Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com>
This commit is contained in:
Jimmy Chu
2021-03-29 21:33:28 +08:00
committed by GitHub
parent db74a34877
commit c8fced2019
7 changed files with 450 additions and 236 deletions
+5 -4
View File
@@ -1,6 +1,6 @@
[package]
name = "pallet-example"
version = "2.0.0"
version = "3.0.0"
authors = ["Parity Technologies <admin@parity.io>"]
edition = "2018"
license = "Unlicense"
@@ -21,8 +21,8 @@ pallet-balances = { version = "3.0.0", default-features = false, path = "../bala
sp-runtime = { version = "3.0.0", default-features = false, path = "../../primitives/runtime" }
sp-std = { version = "3.0.0", default-features = false, path = "../../primitives/std" }
sp-io = { version = "3.0.0", default-features = false, path = "../../primitives/io" }
frame-benchmarking = { version = "3.1.0", default-features = false, path = "../benchmarking", optional = true }
log = { version = "0.4.14", default-features = false }
[dev-dependencies]
sp-core = { version = "3.0.0", path = "../../primitives/core", default-features = false }
@@ -30,14 +30,15 @@ sp-core = { version = "3.0.0", path = "../../primitives/core", default-features
[features]
default = ["std"]
std = [
"serde",
"codec/std",
"sp-runtime/std",
"frame-benchmarking/std",
"frame-support/std",
"frame-system/std",
"log/std",
"pallet-balances/std",
"serde",
"sp-io/std",
"sp-runtime/std",
"sp-std/std"
]
runtime-benchmarks = ["frame-benchmarking"]
@@ -0,0 +1,76 @@
// This file is part of Substrate.
// Copyright (C) 2019-2021 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.
//! Benchmarking for pallet-example.
#![cfg(feature = "runtime-benchmarks")]
use crate::*;
use frame_benchmarking::{benchmarks, whitelisted_caller, impl_benchmark_test_suite};
use frame_system::RawOrigin;
// To actually run this benchmark on pallet-example, we need to put this pallet into the
// runtime and compile it with `runtime-benchmarks` feature. The detail procedures are
// documented at:
// https://substrate.dev/docs/en/knowledgebase/runtime/benchmarking#how-to-benchmark
//
// The auto-generated weight estimate of this pallet is copied over to the `weights.rs` file.
// The exact command of how the estimate generated is printed at the top of the file.
// Details on using the benchmarks macro can be seen at:
// https://substrate.dev/rustdocs/v3.0.0/frame_benchmarking/macro.benchmarks.html
benchmarks!{
// This will measure the execution time of `set_dummy` for b in [1..1000] range.
set_dummy_benchmark {
// This is the benchmark setup phase
let b in 1 .. 1000;
}: set_dummy(RawOrigin::Root, b.into()) // The execution phase is just running `set_dummy` extrinsic call
verify {
// This is the optional benchmark verification phase, asserting certain states.
assert_eq!(Pallet::<T>::dummy(), Some(b.into()))
}
// This will measure the execution time of `accumulate_dummy` for b in [1..1000] range.
// The benchmark execution phase is shorthanded. When the name of the benchmark case is the same
// as the extrinsic call. `_(...)` is used to represent the extrinsic name.
// The benchmark verification phase is omitted.
accumulate_dummy {
let b in 1 .. 1000;
// The caller account is whitelisted for DB reads/write by the benchmarking macro.
let caller: T::AccountId = whitelisted_caller();
}: _(RawOrigin::Signed(caller), b.into())
// This will measure the execution time of sorting a vector.
sort_vector {
let x in 0 .. 10000;
let mut m = Vec::<u32>::new();
for i in (0..x).rev() {
m.push(i);
}
}: {
// The benchmark execution phase could also be a closure with custom code
m.sort();
}
}
// This line generates test cases for benchmarking, and could be run by:
// `cargo test -p pallet-example --all-features`, you will see an additional line of:
// `test benchmarking::benchmark_tests::test_benchmarks ... ok` in the result.
//
// The line generates three steps per benchmark, with repeat=1 and the three steps are
// [low, mid, high] of the range.
impl_benchmark_test_suite!(Pallet, crate::tests::new_test_ext(), crate::tests::Test);
+77 -230
View File
@@ -255,28 +255,45 @@
// Ensure we're `no_std` when compiling for Wasm.
#![cfg_attr(not(feature = "std"), no_std)]
use sp_std::marker::PhantomData;
use sp_std::{
prelude::*,
marker::PhantomData
};
use frame_support::{
dispatch::DispatchResult, traits::IsSubType,
weights::{DispatchClass, ClassifyDispatch, WeighData, Weight, PaysFee, Pays},
};
use sp_std::prelude::*;
use frame_system::{ensure_signed};
use codec::{Encode, Decode};
use sp_runtime::{
traits::{
SignedExtension, Bounded, SaturatedConversion, DispatchInfoOf,
SignedExtension, Bounded, SaturatedConversion, DispatchInfoOf, Saturating
},
transaction_validity::{
ValidTransaction, TransactionValidityError, InvalidTransaction, TransactionValidity,
},
};
use log::info;
// Re-export pallet items so that they can be accessed from the crate namespace.
pub use pallet::*;
#[cfg(test)]
mod tests;
mod benchmarking;
pub mod weights;
pub use weights::*;
/// A type alias for the balance type from this pallet's point of view.
type BalanceOf<T> = <T as pallet_balances::Config>::Balance;
const MILLICENTS: u32 = 1_000_000_000;
// A custom weight calculator tailored for the dispatch call `set_dummy()`. This actually examines
// the arguments and makes a decision based upon them.
//
// The `WeightData<T>` trait has access to the arguments of the dispatch that it wants to assign a
// weight to. Nonetheless, the trait itself can not make any assumptions about what the generic type
// weight to. Nonetheless, the trait itself cannot make any assumptions about what the generic type
// of the arguments (`T`) is. Based on our needs, we could replace `T` with a more concrete type
// while implementing the trait. The `pallet::weight` expects whatever implements `WeighData<T>` to
// replace `T` with a tuple of the dispatch arguments. This is exactly how we will craft the
@@ -286,13 +303,22 @@ use sp_runtime::{
// - The final weight of each dispatch is calculated as the argument of the call multiplied by the
// parameter given to the `WeightForSetDummy`'s constructor.
// - assigns a dispatch class `operational` if the argument of the call is more than 1000.
//
// More information can be read at:
// - https://substrate.dev/docs/en/knowledgebase/learn-substrate/weight
// - https://substrate.dev/docs/en/knowledgebase/runtime/fees#default-weight-annotations
//
// Manually configuring weight is an advanced operation and what you really need may well be
// fulfilled by running the benchmarking toolchain. Refer to `benchmarking.rs` file.
struct WeightForSetDummy<T: pallet_balances::Config>(BalanceOf<T>);
impl<T: pallet_balances::Config> WeighData<(&BalanceOf<T>,)> for WeightForSetDummy<T>
{
fn weigh_data(&self, target: (&BalanceOf<T>,)) -> Weight {
let multiplier = self.0;
(*target.0 * multiplier).saturated_into::<Weight>()
// *target.0 is the amount passed into the extrinsic
let cents = *target.0 / <BalanceOf<T>>::from(MILLICENTS);
(cents * multiplier).saturated_into::<Weight>()
}
}
@@ -312,12 +338,6 @@ impl<T: pallet_balances::Config> PaysFee<(&BalanceOf<T>,)> for WeightForSetDummy
}
}
/// A type alias for the balance type from this pallet's point of view.
type BalanceOf<T> = <T as pallet_balances::Config>::Balance;
// Re-export pallet items so that they can be accessed from the crate namespace.
pub use pallet::*;
// Definition of the pallet logic, to be aggregated at runtime definition through
// `construct_runtime`.
#[frame_support::pallet]
@@ -334,8 +354,15 @@ pub mod pallet {
/// `frame_system::Config` should always be included.
#[pallet::config]
pub trait Config: pallet_balances::Config + frame_system::Config {
// Setting a constant config parameter from the runtime
#[pallet::constant]
type MagicNumber: Get<Self::Balance>;
/// The overarching event type.
type Event: From<Event<Self>> + IsType<<Self as frame_system::Config>::Event>;
/// Type representing the weight of this pallet
type WeightInfo: WeightInfo;
}
// Simple declaration of the `Pallet` type. It is placeholder we use to implement traits and
@@ -354,14 +381,12 @@ pub mod pallet {
fn on_initialize(_n: T::BlockNumber) -> Weight {
// Anything that needs to be done at the start of the block.
// We don't do anything here.
0
}
// `on_finalize` is executed at the end of block after all extrinsic are dispatched.
fn on_finalize(_n: T::BlockNumber) {
// We just kill our dummy storage item.
<Dummy<T>>::kill();
// Perform necessary data/state clean up here.
}
// A runtime code run after every block and have access to extended set of APIs.
@@ -370,7 +395,9 @@ pub mod pallet {
fn offchain_worker(_n: T::BlockNumber) {
// We don't do anything here.
// but we could dispatch extrinsic (transaction/unsigned/inherent) using
// sp_io::submit_extrinsic
// sp_io::submit_extrinsic.
// To see example on offchain worker, please refer to example-offchain-worker pallet
// accompanied in this repository.
}
}
@@ -455,11 +482,16 @@ pub mod pallet {
// difficulty) of the transaction and the latter demonstrates the [`DispatchClass`] of the
// call. A higher weight means a larger transaction (less of which can be placed in a
// single block).
#[pallet::weight(0)]
//
// The weight for this extrinsic we rely on the auto-generated `WeightInfo` from the benchmark
// toolchain.
#[pallet::weight(
<T as pallet::Config>::WeightInfo::accumulate_dummy((*increase_by).saturated_into())
)]
pub(super) fn accumulate_dummy(
origin: OriginFor<T>,
increase_by: T::Balance
) -> DispatchResultWithPostInfo {
) -> DispatchResult {
// This is a public call, so we ensure that the origin is some signed account.
let _sender = ensure_signed(origin)?;
@@ -478,15 +510,16 @@ pub mod pallet {
// Here's the new one of read and then modify the value.
<Dummy<T>>::mutate(|dummy| {
let new_dummy = dummy.map_or(increase_by, |dummy| dummy + increase_by);
// Using `saturating_add` instead of a regular `+` to avoid overflowing
let new_dummy = dummy.map_or(increase_by, |d| d.saturating_add(increase_by));
*dummy = Some(new_dummy);
});
// Let's deposit an event to let the outside world know this happened.
Self::deposit_event(Event::Dummy(increase_by));
Self::deposit_event(Event::AccumulateDummy(increase_by));
// All good, no refund.
Ok(().into())
Ok(())
}
/// A privileged call; in this case it resets our dummy value to something new.
@@ -496,17 +529,28 @@ pub mod pallet {
// calls to be executed - we don't need to care why. Because it's privileged, we can
// assume it's a one-off operation and substantial processing/storage/memory can be used
// without worrying about gameability or attack scenarios.
//
// The weight for this extrinsic we use our own weight object `WeightForSetDummy` to determine
// its weight
#[pallet::weight(WeightForSetDummy::<T>(<BalanceOf<T>>::from(100u32)))]
fn set_dummy(
pub(super) fn set_dummy(
origin: OriginFor<T>,
#[pallet::compact] new_value: T::Balance,
) -> DispatchResultWithPostInfo {
) -> DispatchResult {
ensure_root(origin)?;
// Print out log or debug message in the console via log::{error, warn, info, debug, trace},
// accepting format strings similar to `println!`.
// https://substrate.dev/rustdocs/v3.0.0/log/index.html
info!("New value is now: {:?}", new_value);
// Put the new value into storage.
<Dummy<T>>::put(new_value);
Self::deposit_event(Event::SetDummy(new_value));
// All good, no refund.
Ok(().into())
Ok(())
}
}
@@ -520,7 +564,9 @@ pub mod pallet {
pub enum Event<T: Config> {
// Just a normal `enum`, here's a dummy event to ensure it compiles.
/// Dummy event, just here so there's a generic type that's used.
Dummy(BalanceOf<T>),
AccumulateDummy(BalanceOf<T>),
SetDummy(BalanceOf<T>),
SetBar(T::AccountId, BalanceOf<T>),
}
// pallet::storage attributes allow for type-safe usage of the Substrate storage database,
@@ -545,14 +591,13 @@ pub mod pallet {
// A map that has enumerable entries.
#[pallet::storage]
#[pallet::getter(fn bar)]
pub(super) type Bar<T: Config> = StorageMap<_, Blake2_128Concat, T::AccountId, T::Balance, ValueQuery>;
pub(super) type Bar<T: Config> = StorageMap<_, Blake2_128Concat, T::AccountId, T::Balance>;
// this one uses the query kind: `ValueQuery`, we'll demonstrate the usage of 'mutate' API.
#[pallet::storage]
#[pallet::getter(fn foo)]
pub(super) type Foo<T: Config> = StorageValue<_, T::Balance, ValueQuery>;
// The genesis config type.
#[pallet::genesis_config]
pub struct GenesisConfig<T: Config> {
@@ -600,7 +645,7 @@ impl<T: Config> Pallet<T> {
let prev = <Foo<T>>::get();
// Because Foo has 'default', the type of 'foo' in closure is the raw type instead of an Option<> type.
let result = <Foo<T>>::mutate(|foo| {
*foo = *foo + increase_by;
*foo = foo.saturating_add(increase_by);
*foo
});
assert!(prev + increase_by == result);
@@ -640,11 +685,11 @@ impl<T: Config> Pallet<T> {
// types defined in the runtime. Lookup `pub type SignedExtra = (...)` in `node/runtime` and
// `node-template` for an example of this.
/// A simple signed extension that checks for the `set_dummy` call. In that case, it increases the
/// priority and prints some log.
///
/// Additionally, it drops any transaction with an encoded length higher than 200 bytes. No
/// particular reason why, just to demonstrate the power of signed extensions.
// A simple signed extension that checks for the `set_dummy` call. In that case, it increases the
// priority and prints some log.
//
// Additionally, it drops any transaction with an encoded length higher than 200 bytes. No
// particular reason why, just to demonstrate the power of signed extensions.
#[derive(Encode, Decode, Clone, Eq, PartialEq)]
pub struct WatchDummy<T: Config + Send + Sync>(PhantomData<T>);
@@ -691,201 +736,3 @@ where
}
}
}
#[cfg(feature = "runtime-benchmarks")]
mod benchmarking {
use super::*;
use frame_benchmarking::{benchmarks, account, impl_benchmark_test_suite};
use frame_system::RawOrigin;
benchmarks!{
// This will measure the execution time of `accumulate_dummy` for b in [1..1000] range.
accumulate_dummy {
let b in 1 .. 1000;
let caller = account("caller", 0, 0);
}: _ (RawOrigin::Signed(caller), b.into())
// This will measure the execution time of `set_dummy` for b in [1..1000] range.
set_dummy {
let b in 1 .. 1000;
}: set_dummy (RawOrigin::Root, b.into())
// This will measure the execution time of `set_dummy` for b in [1..10] range.
another_set_dummy {
let b in 1 .. 10;
}: set_dummy (RawOrigin::Root, b.into())
// This will measure the execution time of sorting a vector.
sort_vector {
let x in 0 .. 10000;
let mut m = Vec::<u32>::new();
for i in (0..x).rev() {
m.push(i);
}
}: {
m.sort();
}
}
impl_benchmark_test_suite!(Pallet, crate::tests::new_test_ext(), crate::tests::Test);
}
#[cfg(test)]
mod tests {
use super::*;
use frame_support::{
assert_ok, parameter_types,
weights::{DispatchInfo, GetDispatchInfo}, traits::{OnInitialize, OnFinalize}
};
use sp_core::H256;
// The testing primitives are very useful for avoiding having to work with signatures
// or public keys. `u64` is used as the `AccountId` and no `Signature`s are required.
use sp_runtime::{
testing::Header, BuildStorage,
traits::{BlakeTwo256, IdentityLookup},
};
// Reexport crate as its pallet name for construct_runtime.
use crate as pallet_example;
type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic<Test>;
type Block = frame_system::mocking::MockBlock<Test>;
// For testing the pallet, we construct a mock runtime.
frame_support::construct_runtime!(
pub enum Test where
Block = Block,
NodeBlock = Block,
UncheckedExtrinsic = UncheckedExtrinsic,
{
System: frame_system::{Pallet, Call, Config, Storage, Event<T>},
Balances: pallet_balances::{Pallet, Call, Storage, Config<T>, Event<T>},
Example: pallet_example::{Pallet, Call, Storage, Config<T>, Event<T>},
}
);
parameter_types! {
pub const BlockHashCount: u64 = 250;
pub BlockWeights: frame_system::limits::BlockWeights =
frame_system::limits::BlockWeights::simple_max(1024);
}
impl frame_system::Config for Test {
type BaseCallFilter = ();
type BlockWeights = ();
type BlockLength = ();
type DbWeight = ();
type Origin = Origin;
type Index = u64;
type BlockNumber = u64;
type Hash = H256;
type Call = Call;
type Hashing = BlakeTwo256;
type AccountId = u64;
type Lookup = IdentityLookup<Self::AccountId>;
type Header = Header;
type Event = Event;
type BlockHashCount = BlockHashCount;
type Version = ();
type PalletInfo = PalletInfo;
type AccountData = pallet_balances::AccountData<u64>;
type OnNewAccount = ();
type OnKilledAccount = ();
type SystemWeightInfo = ();
type SS58Prefix = ();
}
parameter_types! {
pub const ExistentialDeposit: u64 = 1;
}
impl pallet_balances::Config for Test {
type MaxLocks = ();
type Balance = u64;
type DustRemoval = ();
type Event = Event;
type ExistentialDeposit = ExistentialDeposit;
type AccountStore = System;
type WeightInfo = ();
}
impl Config for Test {
type Event = Event;
}
// This function basically just builds a genesis storage key/value store according to
// our desired mockup.
pub fn new_test_ext() -> sp_io::TestExternalities {
let t = GenesisConfig {
// We use default for brevity, but you can configure as desired if needed.
frame_system: Default::default(),
pallet_balances: Default::default(),
pallet_example: pallet_example::GenesisConfig {
dummy: 42,
// we configure the map with (key, value) pairs.
bar: vec![(1, 2), (2, 3)],
foo: 24,
},
}.build_storage().unwrap();
t.into()
}
#[test]
fn it_works_for_optional_value() {
new_test_ext().execute_with(|| {
// Check that GenesisBuilder works properly.
assert_eq!(Example::dummy(), Some(42));
// Check that accumulate works when we have Some value in Dummy already.
assert_ok!(Example::accumulate_dummy(Origin::signed(1), 27));
assert_eq!(Example::dummy(), Some(69));
// Check that finalizing the block removes Dummy from storage.
<Example as OnFinalize<u64>>::on_finalize(1);
assert_eq!(Example::dummy(), None);
// Check that accumulate works when we Dummy has None in it.
<Example as OnInitialize<u64>>::on_initialize(2);
assert_ok!(Example::accumulate_dummy(Origin::signed(1), 42));
assert_eq!(Example::dummy(), Some(42));
});
}
#[test]
fn it_works_for_default_value() {
new_test_ext().execute_with(|| {
assert_eq!(Example::foo(), 24);
assert_ok!(Example::accumulate_foo(Origin::signed(1), 1));
assert_eq!(Example::foo(), 25);
});
}
#[test]
fn signed_ext_watch_dummy_works() {
new_test_ext().execute_with(|| {
let call = <pallet_example::Call<Test>>::set_dummy(10).into();
let info = DispatchInfo::default();
assert_eq!(
WatchDummy::<Test>(PhantomData).validate(&1, &call, &info, 150)
.unwrap()
.priority,
u64::max_value(),
);
assert_eq!(
WatchDummy::<Test>(PhantomData).validate(&1, &call, &info, 250),
InvalidTransaction::ExhaustsResources.into(),
);
})
}
#[test]
fn weights_work() {
// must have a defined weight.
let default_call = <pallet_example::Call<Test>>::accumulate_dummy(10);
let info = default_call.get_dispatch_info();
// aka. `let info = <Call<Test> as GetDispatchInfo>::get_dispatch_info(&default_call);`
assert_eq!(info.weight, 0);
// must have a custom weight of `100 * arg = 2000`
let custom_call = <pallet_example::Call<Test>>::set_dummy(20);
let info = custom_call.get_dispatch_info();
assert_eq!(info.weight, 2000);
}
}
+189
View File
@@ -0,0 +1,189 @@
// This file is part of Substrate.
// Copyright (C) 2019-2021 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.
//! Tests for pallet-example.
use crate::*;
use frame_support::{
assert_ok, parameter_types,
weights::{DispatchInfo, GetDispatchInfo}, traits::OnInitialize
};
use sp_core::H256;
// The testing primitives are very useful for avoiding having to work with signatures
// or public keys. `u64` is used as the `AccountId` and no `Signature`s are required.
use sp_runtime::{
testing::Header, BuildStorage,
traits::{BlakeTwo256, IdentityLookup},
};
// Reexport crate as its pallet name for construct_runtime.
use crate as pallet_example;
type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic<Test>;
type Block = frame_system::mocking::MockBlock<Test>;
// For testing the pallet, we construct a mock runtime.
frame_support::construct_runtime!(
pub enum Test where
Block = Block,
NodeBlock = Block,
UncheckedExtrinsic = UncheckedExtrinsic,
{
System: frame_system::{Pallet, Call, Config, Storage, Event<T>},
Balances: pallet_balances::{Pallet, Call, Storage, Config<T>, Event<T>},
Example: pallet_example::{Pallet, Call, Storage, Config<T>, Event<T>},
}
);
parameter_types! {
pub const BlockHashCount: u64 = 250;
pub BlockWeights: frame_system::limits::BlockWeights =
frame_system::limits::BlockWeights::simple_max(1024);
}
impl frame_system::Config for Test {
type BaseCallFilter = ();
type BlockWeights = ();
type BlockLength = ();
type DbWeight = ();
type Origin = Origin;
type Index = u64;
type BlockNumber = u64;
type Hash = H256;
type Call = Call;
type Hashing = BlakeTwo256;
type AccountId = u64;
type Lookup = IdentityLookup<Self::AccountId>;
type Header = Header;
type Event = Event;
type BlockHashCount = BlockHashCount;
type Version = ();
type PalletInfo = PalletInfo;
type AccountData = pallet_balances::AccountData<u64>;
type OnNewAccount = ();
type OnKilledAccount = ();
type SystemWeightInfo = ();
type SS58Prefix = ();
}
parameter_types! {
pub const ExistentialDeposit: u64 = 1;
}
impl pallet_balances::Config for Test {
type MaxLocks = ();
type Balance = u64;
type DustRemoval = ();
type Event = Event;
type ExistentialDeposit = ExistentialDeposit;
type AccountStore = System;
type WeightInfo = ();
}
parameter_types! {
pub const MagicNumber: u64 = 1_000_000_000;
}
impl Config for Test {
type MagicNumber = MagicNumber;
type Event = Event;
type WeightInfo = ();
}
// This function basically just builds a genesis storage key/value store according to
// our desired mockup.
pub fn new_test_ext() -> sp_io::TestExternalities {
let t = GenesisConfig {
// We use default for brevity, but you can configure as desired if needed.
frame_system: Default::default(),
pallet_balances: Default::default(),
pallet_example: pallet_example::GenesisConfig {
dummy: 42,
// we configure the map with (key, value) pairs.
bar: vec![(1, 2), (2, 3)],
foo: 24,
},
}.build_storage().unwrap();
t.into()
}
#[test]
fn it_works_for_optional_value() {
new_test_ext().execute_with(|| {
// Check that GenesisBuilder works properly.
let val1 = 42;
let val2 = 27;
assert_eq!(Example::dummy(), Some(val1));
// Check that accumulate works when we have Some value in Dummy already.
assert_ok!(Example::accumulate_dummy(Origin::signed(1), val2));
assert_eq!(Example::dummy(), Some(val1 + val2));
// Check that accumulate works when we Dummy has None in it.
<Example as OnInitialize<u64>>::on_initialize(2);
assert_ok!(Example::accumulate_dummy(Origin::signed(1), val1));
assert_eq!(Example::dummy(), Some(val1 + val2 + val1));
});
}
#[test]
fn it_works_for_default_value() {
new_test_ext().execute_with(|| {
assert_eq!(Example::foo(), 24);
assert_ok!(Example::accumulate_foo(Origin::signed(1), 1));
assert_eq!(Example::foo(), 25);
});
}
#[test]
fn set_dummy_works() {
new_test_ext().execute_with(|| {
let test_val = 133;
assert_ok!(Example::set_dummy(Origin::root(), test_val.into()));
assert_eq!(Example::dummy(), Some(test_val));
});
}
#[test]
fn signed_ext_watch_dummy_works() {
new_test_ext().execute_with(|| {
let call = <pallet_example::Call<Test>>::set_dummy(10).into();
let info = DispatchInfo::default();
assert_eq!(
WatchDummy::<Test>(PhantomData).validate(&1, &call, &info, 150)
.unwrap()
.priority,
u64::max_value(),
);
assert_eq!(
WatchDummy::<Test>(PhantomData).validate(&1, &call, &info, 250),
InvalidTransaction::ExhaustsResources.into(),
);
})
}
#[test]
fn weights_work() {
// must have a defined weight.
let default_call = <pallet_example::Call<Test>>::accumulate_dummy(10);
let info1 = default_call.get_dispatch_info();
// aka. `let info = <Call<Test> as GetDispatchInfo>::get_dispatch_info(&default_call);`
assert!(info1.weight > 0);
// `set_dummy` is simpler than `accumulate_dummy`, and the weight
// should be less.
let custom_call = <pallet_example::Call<Test>>::set_dummy(20);
let info2 = custom_call.get_dispatch_info();
assert!(info1.weight > info2.weight);
}
+100
View File
@@ -0,0 +1,100 @@
// This file is part of Substrate.
// Copyright (C) 2021 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.
//! Autogenerated weights for pallet_example
//!
//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 3.0.0
//! DATE: 2021-03-15, STEPS: `[100, ]`, REPEAT: 10, LOW RANGE: `[]`, HIGH RANGE: `[]`
//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 128
// Executed Command:
// ./target/release/substrate
// benchmark
// --chain
// dev
// --execution
// wasm
// --wasm-execution
// compiled
// --pallet
// pallet_example
// --extrinsic
// *
// --steps
// 100
// --repeat
// 10
// --raw
// --output
// ./
// --template
// ./.maintain/frame-weight-template.hbs
#![allow(unused_parens)]
#![allow(unused_imports)]
use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}};
use sp_std::marker::PhantomData;
/// Weight functions needed for pallet_example.
pub trait WeightInfo {
fn set_dummy_benchmark(b: u32, ) -> Weight;
fn accumulate_dummy(b: u32, ) -> Weight;
fn sort_vector(x: u32, ) -> Weight;
}
/// Weights for pallet_example using the Substrate node and recommended hardware.
pub struct SubstrateWeight<T>(PhantomData<T>);
impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
fn set_dummy_benchmark(b: u32, ) -> Weight {
(5_834_000 as Weight)
.saturating_add((24_000 as Weight).saturating_mul(b as Weight))
.saturating_add(T::DbWeight::get().writes(1 as Weight))
}
fn accumulate_dummy(b: u32, ) -> Weight {
(51_353_000 as Weight)
.saturating_add((14_000 as Weight).saturating_mul(b as Weight))
.saturating_add(T::DbWeight::get().reads(1 as Weight))
.saturating_add(T::DbWeight::get().writes(1 as Weight))
}
fn sort_vector(x: u32, ) -> Weight {
(2_569_000 as Weight)
// Standard Error: 0
.saturating_add((4_000 as Weight).saturating_mul(x as Weight))
}
}
// For backwards compatibility and tests
impl WeightInfo for () {
fn set_dummy_benchmark(b: u32, ) -> Weight {
(5_834_000 as Weight)
.saturating_add((24_000 as Weight).saturating_mul(b as Weight))
.saturating_add(RocksDbWeight::get().writes(1 as Weight))
}
fn accumulate_dummy(b: u32, ) -> Weight {
(51_353_000 as Weight)
.saturating_add((14_000 as Weight).saturating_mul(b as Weight))
.saturating_add(RocksDbWeight::get().reads(1 as Weight))
.saturating_add(RocksDbWeight::get().writes(1 as Weight))
}
fn sort_vector(x: u32, ) -> Weight {
(2_569_000 as Weight)
// Standard Error: 0
.saturating_add((4_000 as Weight).saturating_mul(x as Weight))
}
}