use frame_support::sp_runtime::{traits::Dispatchable, DispatchResultWithInfo};
use frame_system::pallet_prelude::BlockNumberFor;
use super::Sandbox;
use crate::{EventRecordOf, Runtime, RuntimeCall};
impl<R: Runtime> Sandbox<R> {
pub fn block_number(&mut self) -> BlockNumberFor<R::Config> {
self.execute_with(|| frame_system::Pallet::<R::Config>::block_number())
}
pub fn events(&mut self) -> Vec<EventRecordOf<R::Config>> {
self.execute_with(frame_system::Pallet::<R::Config>::events)
}
pub fn reset_events(&mut self) {
self.execute_with(frame_system::Pallet::<R::Config>::reset_events)
}
pub fn runtime_call<Origin: Into<<RuntimeCall<R::Config> as Dispatchable>::RuntimeOrigin>>(
&mut self,
call: RuntimeCall<R::Config>,
origin: Origin,
) -> DispatchResultWithInfo<<RuntimeCall<R::Config> as Dispatchable>::PostInfo> {
self.execute_with(|| call.dispatch(origin.into()))
}
}
#[cfg(test)]
mod tests {
use frame_support::sp_runtime::{traits::Dispatchable, DispatchResultWithInfo};
use crate::{
runtime::{minimal::RuntimeEvent, ConfigOf, MinimalRuntime, Runtime},
AccountId32, RuntimeCall, Sandbox,
};
type RuntimeCallOf<R> = RuntimeCall<ConfigOf<R>>;
fn make_transfer(
sandbox: &mut Sandbox<MinimalRuntime>,
dest: AccountId32,
value: u128,
) -> DispatchResultWithInfo<<RuntimeCallOf<MinimalRuntime> as Dispatchable>::PostInfo> {
assert_ne!(
MinimalRuntime::default_actor(),
dest,
"make_transfer should send to account different than default_actor"
);
sandbox.runtime_call(
RuntimeCall::<ConfigOf<MinimalRuntime>>::Balances(pallet_balances::Call::<
ConfigOf<MinimalRuntime>,
>::transfer_allow_death {
dest: dest.into(),
value,
}),
Some(MinimalRuntime::default_actor()),
)
}
#[test]
fn dry_run_works() {
let mut sandbox = Sandbox::<MinimalRuntime>::new().expect("Failed to create sandbox");
let actor = MinimalRuntime::default_actor();
let initial_balance = sandbox.free_balance(&actor);
sandbox.dry_run(|runtime| {
runtime.mint_into(actor.clone(), 100).unwrap();
assert_eq!(runtime.free_balance(&actor), initial_balance + 100);
});
assert_eq!(sandbox.free_balance(&actor), initial_balance);
}
#[test]
fn runtime_call_works() {
let mut sandbox = Sandbox::<MinimalRuntime>::new().expect("Failed to create sandbox");
const RECIPIENT: AccountId32 = AccountId32::new([2u8; 32]);
let initial_balance = sandbox.free_balance(&RECIPIENT);
let result = make_transfer(&mut sandbox, RECIPIENT, 100);
assert!(result.is_ok());
let expected_balance = initial_balance + 100;
assert_eq!(sandbox.free_balance(&RECIPIENT), expected_balance);
}
#[test]
fn current_events() {
let mut sandbox = Sandbox::<MinimalRuntime>::new().expect("Failed to create sandbox");
const RECIPIENT: AccountId32 = AccountId32::new([2u8; 32]);
let events_before = sandbox.events();
assert!(events_before.is_empty());
make_transfer(&mut sandbox, RECIPIENT, 1).expect("Failed to make transfer");
let events_after = sandbox.events();
assert!(!events_after.is_empty());
assert!(matches!(
events_after.last().unwrap().event,
RuntimeEvent::Balances(_)
));
}
#[test]
fn resetting_events() {
let mut sandbox = Sandbox::<MinimalRuntime>::new().expect("Failed to create sandbox");
const RECIPIENT: AccountId32 = AccountId32::new([3u8; 32]);
make_transfer(&mut sandbox, RECIPIENT.clone(), 1).expect("Failed to make transfer");
assert!(!sandbox.events().is_empty());
sandbox.reset_events();
assert!(sandbox.events().is_empty());
make_transfer(&mut sandbox, RECIPIENT, 1).expect("Failed to make transfer");
assert!(!sandbox.events().is_empty());
}
}