mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-13 07:01:05 +00:00
Generate Unit Tests for Benchmarks (#5527)
* Update to latest staking * generate tests for benchmarking * add tests, fix warnings * starting on democracy * impl_benchmark_tests * Way more readable * add test feature flag (does this work?) * Fix `successful_origin` impl * democracry benchmark tests * Fix example benchmarks, add tests * identity benchmark tests * Update im-online benchmark tests * try to add session benchmarking tests (problem with mock) * staking and timestamp * add test for treasury, issue with dynamic contains * utility * Vesting * test instead of check * hide until we figure out what is wrong * add docs * close code * Create custom mock for session-pallet-benchmarking * Use refcell pattern * make un-pub * test-linux-stable includes `runtime-benchmarks` feature * Revert "test-linux-stable includes `runtime-benchmarks` feature" This reverts commit a2dab38abd18ac3eb8a6220e4a00e687740bd38c. * run tests in `--release` * undo balance change * build wasm
This commit is contained in:
@@ -29,6 +29,7 @@ pub use analysis::Analysis;
|
||||
#[doc(hidden)]
|
||||
pub use sp_io::storage::root as storage_root;
|
||||
pub use sp_runtime::traits::Dispatchable;
|
||||
pub use paste;
|
||||
|
||||
/// Construct pallet benchmarks for weighing dispatchables.
|
||||
///
|
||||
@@ -124,6 +125,26 @@ pub use sp_runtime::traits::Dispatchable;
|
||||
/// }: { m.into_iter().collect::<BTreeSet>() }
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// Test functions are automatically generated for each benchmark and are accessible to you when you
|
||||
/// run `cargo test`. All tests are named `test_benchmark_<benchmark_name>`, expect you to pass them
|
||||
/// the Runtime Trait, and run them in a test externalities environment. The test function runs your
|
||||
/// benchmark just like a regular benchmark, but only testing at the lowest and highest values for
|
||||
/// each component. The function will return `Ok(())` if the benchmarks return no errors.
|
||||
///
|
||||
/// You can construct benchmark tests like so:
|
||||
///
|
||||
/// ```ignore
|
||||
/// #[test]
|
||||
/// fn test_benchmarks() {
|
||||
/// new_test_ext().execute_with(|| {
|
||||
/// assert_ok!(test_benchmark_dummy::<Test>());
|
||||
/// assert_err!(test_benchmark_other_name::<Test>(), "Bad origin");
|
||||
/// assert_ok!(test_benchmark_sort_vector::<Test>());
|
||||
/// assert_err!(test_benchmark_broken_benchmark::<Test>(), "You forgot to sort!");
|
||||
/// });
|
||||
/// }
|
||||
/// ```
|
||||
#[macro_export]
|
||||
macro_rules! benchmarks {
|
||||
(
|
||||
@@ -134,9 +155,12 @@ macro_rules! benchmarks {
|
||||
}
|
||||
$( $rest:tt )*
|
||||
) => {
|
||||
$crate::benchmarks_iter!(NO_INSTANCE {
|
||||
$( { $common , $common_from , $common_to , $common_instancer } )*
|
||||
} ( ) $( $rest )* );
|
||||
$crate::benchmarks_iter!(
|
||||
NO_INSTANCE
|
||||
{ $( { $common , $common_from , $common_to , $common_instancer } )* }
|
||||
( )
|
||||
$( $rest )*
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -150,9 +174,12 @@ macro_rules! benchmarks_instance {
|
||||
}
|
||||
$( $rest:tt )*
|
||||
) => {
|
||||
$crate::benchmarks_iter!(INSTANCE {
|
||||
$( { $common , $common_from , $common_to , $common_instancer } )*
|
||||
} ( ) $( $rest )* );
|
||||
$crate::benchmarks_iter!(
|
||||
INSTANCE
|
||||
{ $( { $common , $common_from , $common_to , $common_instancer } )* }
|
||||
( )
|
||||
$( $rest )*
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -168,7 +195,11 @@ macro_rules! benchmarks_iter {
|
||||
$( $rest:tt )*
|
||||
) => {
|
||||
$crate::benchmarks_iter! {
|
||||
$instance { $( $common )* } ( $( $names )* ) $name { $( $code )* }: $name ( $origin $( , $arg )* ) $( $rest )*
|
||||
$instance
|
||||
{ $( $common )* }
|
||||
( $( $names )* )
|
||||
$name { $( $code )* }: $name ( $origin $( , $arg )* )
|
||||
$( $rest )*
|
||||
}
|
||||
};
|
||||
// no instance mutation arm:
|
||||
@@ -181,9 +212,12 @@ macro_rules! benchmarks_iter {
|
||||
) => {
|
||||
$crate::benchmarks_iter! {
|
||||
NO_INSTANCE
|
||||
{ $( $common )* } ( $( $names )* ) $name { $( $code )* }: {
|
||||
{ $( $common )* }
|
||||
( $( $names )* )
|
||||
$name { $( $code )* }: {
|
||||
<Call<T> as $crate::Dispatchable>::dispatch(Call::<T>::$dispatch($($arg),*), $origin.into())?;
|
||||
} $( $rest )*
|
||||
}
|
||||
$( $rest )*
|
||||
}
|
||||
};
|
||||
// instance mutation arm:
|
||||
@@ -196,9 +230,12 @@ macro_rules! benchmarks_iter {
|
||||
) => {
|
||||
$crate::benchmarks_iter! {
|
||||
INSTANCE
|
||||
{ $( $common )* } ( $( $names )* ) $name { $( $code )* }: {
|
||||
{ $( $common )* }
|
||||
( $( $names )* )
|
||||
$name { $( $code )* }: {
|
||||
<Call<T, I> as $crate::Dispatchable>::dispatch(Call::<T, I>::$dispatch($($arg),*), $origin.into())?;
|
||||
} $( $rest )*
|
||||
}
|
||||
$( $rest )*
|
||||
}
|
||||
};
|
||||
// iteration arm:
|
||||
@@ -210,14 +247,26 @@ macro_rules! benchmarks_iter {
|
||||
$( $rest:tt )*
|
||||
) => {
|
||||
$crate::benchmark_backend! {
|
||||
$instance $name { $( $common )* } { } { $eval } { $( $code )* }
|
||||
$instance
|
||||
$name
|
||||
{ $( $common )* }
|
||||
{ }
|
||||
{ $eval }
|
||||
{ $( $code )* }
|
||||
}
|
||||
$crate::benchmarks_iter!( $instance { $( $common )* } ( $( $names )* $name ) $( $rest )* );
|
||||
$crate::benchmarks_iter!(
|
||||
$instance
|
||||
{ $( $common )* }
|
||||
( $( $names )* $name )
|
||||
$( $rest )*
|
||||
);
|
||||
};
|
||||
// iteration-exit arm
|
||||
( $instance:ident { $( $common:tt )* } ( $( $names:ident )* ) ) => {
|
||||
$crate::selected_benchmark!( $instance $( $names ),* );
|
||||
$crate::impl_benchmark!( $instance $( $names ),* );
|
||||
#[cfg(test)]
|
||||
$crate::impl_benchmark_tests!( $( $names ),* );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -703,6 +752,54 @@ macro_rules! impl_benchmark {
|
||||
}
|
||||
}
|
||||
|
||||
// This creates unit tests from the main benchmark macro.
|
||||
// They run the benchmark using the `high` and `low` value for each component
|
||||
// and ensure that everything completes successfully.
|
||||
#[macro_export]
|
||||
macro_rules! impl_benchmark_tests {
|
||||
(
|
||||
$( $name:ident ),*
|
||||
) => {
|
||||
$(
|
||||
$crate::paste::item! {
|
||||
fn [<test_benchmark_ $name>] <T: Trait> () -> Result<(), &'static str>
|
||||
where T: frame_system::Trait
|
||||
{
|
||||
let selected_benchmark = SelectedBenchmark::$name;
|
||||
let components = <SelectedBenchmark as $crate::BenchmarkingSetup<T>>::components(&selected_benchmark);
|
||||
|
||||
for (_, (name, low, high)) in components.iter().enumerate() {
|
||||
// Test only the low and high value, assuming values in the middle won't break
|
||||
for component_value in vec![low, high] {
|
||||
// Select the max value for all the other components.
|
||||
let c: Vec<($crate::BenchmarkParameter, u32)> = components.iter()
|
||||
.enumerate()
|
||||
.map(|(_, (n, _, h))|
|
||||
if n == name {
|
||||
(*n, *component_value)
|
||||
} else {
|
||||
(*n, *h)
|
||||
}
|
||||
)
|
||||
.collect();
|
||||
|
||||
// Set the block number to 1 so events are deposited.
|
||||
frame_system::Module::<T>::set_block_number(1.into());
|
||||
// Set up the externalities environment for the setup we want to benchmark.
|
||||
let closure_to_benchmark = <SelectedBenchmark as $crate::BenchmarkingSetup<T>>::instance(&selected_benchmark, &c)?;
|
||||
// Run the benchmark
|
||||
closure_to_benchmark()?;
|
||||
// Reset the state
|
||||
$crate::benchmarking::wipe_db();
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// This macro adds pallet benchmarks to a `Vec<BenchmarkBatch>` object.
|
||||
///
|
||||
|
||||
@@ -22,7 +22,9 @@ use super::*;
|
||||
use codec::Decode;
|
||||
use sp_std::prelude::*;
|
||||
use sp_runtime::{traits::{BlakeTwo256, IdentityLookup}, testing::{H256, Header}};
|
||||
use frame_support::{dispatch::DispatchResult, decl_module, impl_outer_origin};
|
||||
use frame_support::{
|
||||
dispatch::DispatchResult, decl_module, impl_outer_origin, assert_ok, assert_err, ensure
|
||||
};
|
||||
use frame_system::{RawOrigin, ensure_signed, ensure_none};
|
||||
|
||||
decl_module! {
|
||||
@@ -107,13 +109,24 @@ benchmarks!{
|
||||
}: other_dummy (RawOrigin::Signed(caller), b.into())
|
||||
|
||||
sort_vector {
|
||||
let x in 0 .. 10000;
|
||||
let x in 1 .. 10000;
|
||||
let mut m = Vec::<u32>::new();
|
||||
for i in 0..x {
|
||||
for i in (0..x).rev() {
|
||||
m.push(i);
|
||||
}
|
||||
}: {
|
||||
m.sort();
|
||||
ensure!(m[0] == 0, "You forgot to sort!")
|
||||
}
|
||||
|
||||
broken_benchmark {
|
||||
let x in 1 .. 10000;
|
||||
let mut m = Vec::<u32>::new();
|
||||
for i in (0..x).rev() {
|
||||
m.push(i);
|
||||
}
|
||||
}: {
|
||||
ensure!(m[0] == 0, "You forgot to sort!")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -157,7 +170,7 @@ fn benchmarks_macro_works_for_non_dispatchable() {
|
||||
let selected_benchmark = SelectedBenchmark::sort_vector;
|
||||
|
||||
let components = <SelectedBenchmark as BenchmarkingSetup<Test>>::components(&selected_benchmark);
|
||||
assert_eq!(components, vec![(BenchmarkParameter::x, 0, 10000)]);
|
||||
assert_eq!(components, vec![(BenchmarkParameter::x, 1, 10000)]);
|
||||
|
||||
let closure = <SelectedBenchmark as BenchmarkingSetup<Test>>::instance(
|
||||
&selected_benchmark,
|
||||
@@ -166,3 +179,13 @@ fn benchmarks_macro_works_for_non_dispatchable() {
|
||||
|
||||
assert_eq!(closure(), Ok(()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn benchmarks_generate_unit_tests() {
|
||||
new_test_ext().execute_with(|| {
|
||||
assert_ok!(test_benchmark_dummy::<Test>());
|
||||
assert_err!(test_benchmark_other_name::<Test>(), "Bad origin");
|
||||
assert_ok!(test_benchmark_sort_vector::<Test>());
|
||||
assert_err!(test_benchmark_broken_benchmark::<Test>(), "You forgot to sort!");
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user