diff --git a/runtime/integration-tests/src/generic/cases/example.rs b/runtime/integration-tests/src/generic/cases/example.rs index 9b2467b366..06c9801ec4 100644 --- a/runtime/integration-tests/src/generic/cases/example.rs +++ b/runtime/integration-tests/src/generic/cases/example.rs @@ -123,7 +123,23 @@ fn fudge_transfer_balance() { ) .unwrap(); - //TODO + env.pass(Blocks::ByNumber(1)); + + // Check the state + env.state(|| { + assert_eq!( + pallet_balances::Pallet::::free_balance(Keyring::Bob.to_account_id()), + TRANSFER + ); + }); + + // Check for an even occurred in this block + env.check_event(pallet_balances::Event::Transfer { + from: Keyring::Alice.to_account_id(), + to: Keyring::Bob.to_account_id(), + amount: TRANSFER, + }) + .unwrap(); } fn fudge_call_api() { @@ -142,15 +158,8 @@ fn fudge_call_api() { }) } -// Generate tests for all runtimes crate::test_for_runtimes!([development, altair, centrifuge], transfer_balance); crate::test_for_runtimes!(all, call_api); crate::test_for_runtimes!(all, check_fee); crate::test_for_runtimes!([development], fudge_transfer_balance); crate::test_for_runtimes!([development], fudge_call_api); - -// Output: for `cargo test -p runtime-integration-tests transfer_balance` -// running 6 tests -// test generic::cases::example::transfer_balance::altair ... ok -// test generic::cases::example::transfer_balance::development ... ok -// test generic::cases::example::transfer_balance::centrifuge ... ok diff --git a/runtime/integration-tests/src/generic/environment.rs b/runtime/integration-tests/src/generic/environment.rs index bb0e9d2a7b..a25ef98dee 100644 --- a/runtime/integration-tests/src/generic/environment.rs +++ b/runtime/integration-tests/src/generic/environment.rs @@ -1,5 +1,10 @@ -use cfg_primitives::{Balance, BlockNumber, Moment}; -use sp_runtime::{DispatchResult, Storage}; +use cfg_primitives::{Address, Balance, BlockNumber, Moment}; +use codec::Encode; +use sp_runtime::{ + generic::{Era, SignedPayload}, + traits::{Block, Extrinsic}, + DispatchResult, MultiSignature, Storage, +}; use crate::{generic::runtime::Runtime, utils::accounts::Keyring}; @@ -26,8 +31,42 @@ pub trait Env { /// Load the environment from a storage fn from_storage(storage: Storage) -> Self; + /// Creates an extrinsic, used by mainly by the own environment. + /// To create and submit an extrinsic, see `submit()` + fn create_extrinsic( + &self, + who: Keyring, + call: impl Into, + ) -> ::Extrinsic { + self.state(|| { + let runtime_call = call.into(); + let signed_extra = ( + frame_system::CheckNonZeroSender::::new(), + frame_system::CheckSpecVersion::::new(), + frame_system::CheckTxVersion::::new(), + frame_system::CheckGenesis::::new(), + frame_system::CheckEra::::from(Era::mortal(256, 0)), + frame_system::CheckNonce::::from(0), + frame_system::CheckWeight::::new(), + pallet_transaction_payment::ChargeTransactionPayment::::from(0), + ); + + let raw_payload = + SignedPayload::new(runtime_call.clone(), signed_extra.clone()).unwrap(); + let signature = + MultiSignature::Sr25519(raw_payload.using_encoded(|payload| who.sign(payload))); + + let multi_address = (Address::Id(who.to_account_id()), signature, signed_extra); + + ::Extrinsic::new(runtime_call, Some(multi_address)).unwrap() + }) + } + /// Submit an extrinsic mutating the state - fn submit(&mut self, who: Keyring, call: impl Into) -> DispatchResult; + fn submit(&mut self, who: Keyring, call: impl Into) -> DispatchResult { + let extrinsic = self.create_extrinsic(who, call); + self.__priv_apply_extrinsic(extrinsic) + } /// Pass any number of blocks fn pass(&mut self, blocks: Blocks) { @@ -54,15 +93,7 @@ pub trait Env { self.__priv_build_block(i); if let Blocks::UntilEvent { event, .. } = blocks.clone() { - let found = self.state(|| { - let event: T::RuntimeEventExt = event.into(); - frame_system::Pallet::::events() - .into_iter() - .find(|record| record.event == event) - .is_some() - }); - - if found { + if self.check_event(event).is_some() { break; } } @@ -103,8 +134,7 @@ pub trait Env { frame_system::Pallet::::events() .into_iter() .rev() - .map(|record| record.event.try_into().ok()) - .find_map(|event| event.map(|e| f(e))) + .find_map(|record| record.event.try_into().map(|e| f(e)).ok()) .flatten() }) } @@ -121,4 +151,9 @@ pub trait Env { } fn __priv_build_block(&mut self, i: BlockNumber); + + fn __priv_apply_extrinsic( + &mut self, + extrinsic: ::Extrinsic, + ) -> DispatchResult; } diff --git a/runtime/integration-tests/src/generic/envs/fudge_env.rs b/runtime/integration-tests/src/generic/envs/fudge_env.rs index 4f45a07ecd..0e147649d6 100644 --- a/runtime/integration-tests/src/generic/envs/fudge_env.rs +++ b/runtime/integration-tests/src/generic/envs/fudge_env.rs @@ -1,21 +1,13 @@ pub mod handle; -use cfg_primitives::{Address, BlockNumber}; -use codec::Encode; +use cfg_primitives::BlockNumber; use fudge::primitives::Chain; use handle::{FudgeHandle, ParachainClient}; use sc_client_api::HeaderBackend; use sp_api::{ApiRef, ProvideRuntimeApi}; -use sp_runtime::{ - generic::{BlockId, Era, SignedPayload}, - traits::{Block, Extrinsic}, - DispatchResult, MultiSignature, Storage, -}; +use sp_runtime::{generic::BlockId, traits::Block, DispatchError, DispatchResult, Storage}; -use crate::{ - generic::{environment::Env, runtime::Runtime}, - utils::accounts::Keyring, -}; +use crate::generic::{environment::Env, runtime::Runtime}; /// Trait that represent a runtime with Fudge support pub trait FudgeSupport: Runtime { @@ -30,39 +22,11 @@ pub struct FudgeEnv { impl Env for FudgeEnv { fn from_storage(storage: Storage) -> Self { - Self { - handle: T::FudgeHandle::build(Storage::default(), storage), - } - } - - fn submit(&mut self, who: Keyring, call: impl Into) -> DispatchResult { - let runtime_call = call.into(); - let signed_extra = ( - frame_system::CheckNonZeroSender::::new(), - frame_system::CheckSpecVersion::::new(), - frame_system::CheckTxVersion::::new(), - frame_system::CheckGenesis::::new(), - frame_system::CheckEra::::from(Era::mortal(256, 0)), - frame_system::CheckNonce::::from(0), - frame_system::CheckWeight::::new(), - pallet_transaction_payment::ChargeTransactionPayment::::from(0), - ); - - let raw_payload = SignedPayload::new(runtime_call.clone(), signed_extra.clone()).unwrap(); - let signature = - MultiSignature::Sr25519(raw_payload.using_encoded(|payload| who.sign(payload))); - - let multi_address = (Address::Id(who.to_account_id()), signature, signed_extra); + let mut handle = T::FudgeHandle::build(Storage::default(), storage); - let extrinsic = - ::Extrinsic::new(runtime_call, Some(multi_address)).unwrap(); + handle.evolve(); - self.handle - .parachain_mut() - .append_extrinsic(extrinsic) - .unwrap(); - - Ok(()) + Self { handle } } fn state_mut(&mut self, f: impl FnOnce() -> R) -> R { @@ -76,6 +40,20 @@ impl Env for FudgeEnv { fn __priv_build_block(&mut self, _i: BlockNumber) { self.handle.evolve(); } + + fn __priv_apply_extrinsic( + &mut self, + extrinsic: ::Extrinsic, + ) -> DispatchResult { + self.handle + .parachain_mut() + .append_extrinsic(extrinsic) + .map(|_| ()) + .map_err(|_| { + // More information, issue: https://github.com/centrifuge/fudge/issues/67 + DispatchError::Other("Specific kind of DispatchError not supported by fudge now") + }) + } } type ApiRefOf<'a, T> = ApiRef< diff --git a/runtime/integration-tests/src/generic/envs/fudge_env/handle.rs b/runtime/integration-tests/src/generic/envs/fudge_env/handle.rs index 71cb114300..4a357dc597 100644 --- a/runtime/integration-tests/src/generic/envs/fudge_env/handle.rs +++ b/runtime/integration-tests/src/generic/envs/fudge_env/handle.rs @@ -225,7 +225,7 @@ pub trait FudgeHandle { Some(std::time::Duration::from_millis(START_DATE)), ); - let cidp = Box::new(move |_parent, ()| { + let cidp = Box::new(move |_parent: H256, ()| { let inherent_builder_clone = inherent_builder.clone(); async move { let timestamp = FudgeInherentTimestamp::get_instance(instance_id) diff --git a/runtime/integration-tests/src/generic/envs/runtime_env.rs b/runtime/integration-tests/src/generic/envs/runtime_env.rs index 80fe8d6c22..2faac977a7 100644 --- a/runtime/integration-tests/src/generic/envs/runtime_env.rs +++ b/runtime/integration-tests/src/generic/envs/runtime_env.rs @@ -1,6 +1,6 @@ use std::{cell::RefCell, marker::PhantomData, rc::Rc}; -use cfg_primitives::{Address, AuraId, BlockNumber, Header, Index}; +use cfg_primitives::{AuraId, BlockNumber, Header, Index}; use codec::Encode; use cumulus_primitives_core::PersistedValidationData; use cumulus_primitives_parachain_inherent::ParachainInherentData; @@ -13,16 +13,12 @@ use frame_support::{ use sp_consensus_aura::{Slot, AURA_ENGINE_ID}; use sp_core::{sr25519::Public, H256}; use sp_runtime::{ - generic::{Era, SignedPayload}, traits::{Block, Extrinsic}, - Digest, DigestItem, DispatchError, DispatchResult, MultiSignature, Storage, TransactionOutcome, + Digest, DigestItem, DispatchError, DispatchResult, Storage, TransactionOutcome, }; use sp_timestamp::Timestamp; -use crate::{ - generic::{environment::Env, runtime::Runtime}, - utils::accounts::Keyring, -}; +use crate::generic::{environment::Env, runtime::Runtime}; /// Evironment that interact directly with the runtime, /// without the usage of a client. @@ -52,36 +48,6 @@ impl Env for RuntimeEnv { } } - fn submit(&mut self, who: Keyring, call: impl Into) -> DispatchResult { - self.ext.borrow_mut().execute_with(|| { - let runtime_call = call.into(); - let signed_extra = ( - frame_system::CheckNonZeroSender::::new(), - frame_system::CheckSpecVersion::::new(), - frame_system::CheckTxVersion::::new(), - frame_system::CheckGenesis::::new(), - frame_system::CheckEra::::from(Era::mortal(256, 0)), - frame_system::CheckNonce::::from(self.nonce), - frame_system::CheckWeight::::new(), - pallet_transaction_payment::ChargeTransactionPayment::::from(0), - ); - - let raw_payload = - SignedPayload::new(runtime_call.clone(), signed_extra.clone()).unwrap(); - let signature = - MultiSignature::Sr25519(raw_payload.using_encoded(|payload| who.sign(payload))); - - let multi_address = (Address::Id(who.to_account_id()), signature, signed_extra); - - let extrinsic = - ::Extrinsic::new(runtime_call, Some(multi_address)).unwrap(); - - self.nonce += 1; - - T::apply_extrinsic(extrinsic).unwrap() - }) - } - fn state_mut(&mut self, f: impl FnOnce() -> R) -> R { self.ext.borrow_mut().execute_with(f) } @@ -102,6 +68,13 @@ impl Env for RuntimeEnv { Self::prepare_block(i); }); } + + fn __priv_apply_extrinsic( + &mut self, + extrinsic: ::Extrinsic, + ) -> DispatchResult { + self.state_mut(|| T::apply_extrinsic(extrinsic).unwrap()) + } } impl RuntimeEnv { diff --git a/runtime/integration-tests/src/generic/mod.rs b/runtime/integration-tests/src/generic/mod.rs index 2c63e23078..bb2c574165 100644 --- a/runtime/integration-tests/src/generic/mod.rs +++ b/runtime/integration-tests/src/generic/mod.rs @@ -36,6 +36,17 @@ impl_config!(development_runtime, Development); impl_config!(altair_runtime, Altair); impl_config!(centrifuge_runtime, Centrifuge); +/// Generate tests for all runtimes +/// See `example.rs` file for the usage +/// +/// ```sh +/// Output: for `cargo test -p runtime-integration-tests transfer_balance` +/// running 3 tests +/// +/// test generic::cases::example::transfer_balance::altair ... ok +/// test generic::cases::example::transfer_balance::development ... ok +/// test generic::cases::example::transfer_balance::centrifuge ... ok +/// ``` #[macro_export] macro_rules! test_for_runtimes { ( [ $($runtime:ident),* ], $name:ident ) => { @@ -111,7 +122,7 @@ mod fudge_handles { let relay = Self::build_relay(relay_storage); let parachain = Self::build_parachain(&relay, parachain_storage); - Self { relay, parachain } + Self::new(relay, parachain).unwrap() } fn relay(&self) -> &RelaychainBuilder { diff --git a/runtime/integration-tests/src/generic/runtime.rs b/runtime/integration-tests/src/generic/runtime.rs index 5cb0136bc7..75c2331fb5 100644 --- a/runtime/integration-tests/src/generic/runtime.rs +++ b/runtime/integration-tests/src/generic/runtime.rs @@ -19,6 +19,7 @@ use runtime_common::{ apis, fees::{DealWithFees, WeightToFee}, }; +use sp_core::H256; use sp_runtime::traits::{AccountIdLookup, Block, Dispatchable, Member}; /// Kind of runtime to check in runtime time @@ -116,6 +117,7 @@ pub trait Runtime: /// Block used by the runtime type Block: Block< + Hash = H256, Header = Header, Extrinsic = UncheckedExtrinsic< Address,