diff --git a/pallets/quota/src/benchmarking.rs b/pallets/quota/src/benchmarking.rs index 587ff9cc52a65bdf7649df14aabf77979c6f3cb8..ab8785b0ff1aafb718b04dae62842b01362a3d5a 100644 --- a/pallets/quota/src/benchmarking.rs +++ b/pallets/quota/src/benchmarking.rs @@ -19,46 +19,93 @@ use super::*; use frame_benchmarking::{account, benchmarks}; -// FIXME this is a naïve implementation of benchmarks: -// - without properly prepare data -// - without "verify" blocks -// - without thinking about worst case scenario -// - without writing complexity in the term of refund queue length -// It's there as a seed for benchmark implementation and to use WeightInfo where needed. +fn assert_has_event<T: Config>(generic_event: <T as Config>::RuntimeEvent) { + frame_system::Pallet::<T>::assert_has_event(generic_event.into()); +} benchmarks! { where_clause { where IdtyId<T>: From<u32>, BalanceOf<T>: From<u64>, + T::AccountId: From<[u8; 32]>, } queue_refund { let account: T::AccountId = account("Alice", 1, 1); + let dummy_refund = Refund { + account: account.clone(), + identity: 0u32.into(), + amount: 20u64.into(), + }; let refund = Refund { account, identity: 1u32.into(), amount: 10u64.into(), }; - }: { Pallet::<T>::queue_refund(refund) } + // Complexity is bound to MAX_QUEUD_REFUNDS where an insertion is O(n-1) + for i in 0..MAX_QUEUED_REFUNDS-1 { + Pallet::<T>::queue_refund(dummy_refund.clone()) + } + }: { Pallet::<T>::queue_refund(refund.clone()) } + verify { + assert_eq!(RefundQueue::<T>::get().last(), Some(refund).as_ref()); + assert_eq!(RefundQueue::<T>::get().len() as u32, MAX_QUEUED_REFUNDS); + } spend_quota { - let idty_id = 1u32; - let amount = 1u64; + let idty_id: IdtyId<T> = 1u32.into(); + let amount = 2u64; + IdtyQuota::<T>::insert( + idty_id, + Quota { + last_use: T::BlockNumber::zero(), + amount: 10u64.into(), + }, + ); }: { Pallet::<T>::spend_quota(idty_id.into(), amount.into()) } + verify { + // Initially 10, updated to 11, minus 2 + assert_eq!(IdtyQuota::<T>::get(idty_id).unwrap().amount, 9u64.into()); + } try_refund { let account: T::AccountId = account("Alice", 1, 1); + let idty_id: IdtyId<T> = 1u32.into(); + IdtyQuota::<T>::insert( + idty_id, + Quota { + last_use: T::BlockNumber::zero(), + amount: 10u64.into(), + }, + ); + let _ = CurrencyOf::<T>:: make_free_balance_be( + &T::RefundAccount::get(),u32::MAX.into(), + ); + // The worst-case scenario is when the refund fails + // and can only be triggered if the account is dead, + // in this case by having no balance in the account. let refund = Refund { - account, + account: account.clone(), identity: 1u32.into(), amount: 10u64.into(), }; }: { Pallet::<T>::try_refund(refund) } + verify { +assert_has_event::<T>(Event::<T>::RefundFailed ( account ).into()); + } do_refund { let account: T::AccountId = account("Alice", 1, 1); + let _ = CurrencyOf::<T>:: make_free_balance_be( + &T::RefundAccount::get(),u32::MAX.into(), + ); + // The worst-case scenario is when the refund fails + // and can only be triggered if the account is dead, + // in this case by having no balance in the account. let refund = Refund { - account, + account: account.clone(), identity: 1u32.into(), amount: 10u64.into(), }; - let amount = 5u64.into(); - }: { Pallet::<T>::do_refund(refund, amount) } + }: { Pallet::<T>::try_refund(refund) } + verify { +assert_has_event::<T>(Event::<T>::RefundFailed ( account ).into()); + } }