Skip to content

Commit

Permalink
ForeignInvestments: Unitary tests & fuzzer (#1509)
Browse files Browse the repository at this point in the history
* base mock file

* configure mock pallet with placeholders

* add InvestmentId mock

* add Investment mock

* add TokenSwaps mock

* add StatusNotificationHook mock. mock-builder support for instanciable storages

* add CurrencyConversion mock

* example test compiling with foreign mock

* simplify mock reducing bounds

* add base new invest test case

* finish new invest use case

* add increase_pending_invest

* add more tests

* updates

* update test after rebase

* prepare database for State transition UTs

* add increment transition state UTs

* minor test changes

* add fuzzier skeleon

* reduce unused transitions for fuzzer

* fix taplo

* rebase & fix tests

* fuzzer drafts

* fix mocks

* base fuzzer working

* improve randomness and fix test

* fuzzer fixes

* changes over last rebase

* completed invest fuzzer

* redeem fuzzer working

* remove mock builder artifact

* minor fixes

* fix comments
  • Loading branch information
lemunozm authored Sep 26, 2023
1 parent 255f8fd commit ccb6e2e
Show file tree
Hide file tree
Showing 18 changed files with 1,399 additions and 41 deletions.
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 0 additions & 3 deletions libs/mock-builder/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -345,9 +345,6 @@ macro_rules! execute_call {
($input:expr) => {{
$crate::execute::<CallIds<T>, _, _, _>(|| (), $input)
}};
($input:expr, $gen:expr) => {{
$crate::execute::<CallIds<$gen>, _, _, _>(|| (), $input)
}};
}

/// Execute a function from the function storage for a pallet with instances.
Expand Down
47 changes: 47 additions & 0 deletions libs/mocks/src/currency_conversion.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#[frame_support::pallet]
pub mod pallet {
use cfg_traits::IdentityCurrencyConversion;
use frame_support::pallet_prelude::*;
use mock_builder::{execute_call, register_call};

#[pallet::config]
pub trait Config: frame_system::Config {
type Balance;
type CurrencyId;
}

#[pallet::pallet]
#[pallet::generate_store(pub(super) trait Store)]
pub struct Pallet<T>(_);

#[pallet::storage]
pub(super) type CallIds<T: Config> = StorageMap<
_,
Blake2_128Concat,
<Blake2_128 as frame_support::StorageHasher>::Output,
mock_builder::CallId,
>;

impl<T: Config> Pallet<T> {
pub fn mock_stable_to_stable(
f: impl Fn(T::CurrencyId, T::CurrencyId, T::Balance) -> Result<T::Balance, DispatchError>
+ 'static,
) {
register_call!(move |(a, b, c)| f(a, b, c));
}
}

impl<T: Config> IdentityCurrencyConversion for Pallet<T> {
type Balance = T::Balance;
type Currency = T::CurrencyId;
type Error = DispatchError;

fn stable_to_stable(
a: Self::Currency,
b: Self::Currency,
c: Self::Balance,
) -> Result<Self::Balance, DispatchError> {
execute_call!((a, b, c))
}
}
}
160 changes: 160 additions & 0 deletions libs/mocks/src/investment.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
#[frame_support::pallet]
pub mod pallet {
use cfg_traits::investments::{Investment, InvestmentCollector};
use frame_support::pallet_prelude::*;
use mock_builder::{execute_call, register_call};

#[pallet::config]
pub trait Config: frame_system::Config {
type Amount;
type CurrencyId;
type InvestmentId;
}

#[pallet::pallet]
#[pallet::generate_store(pub(super) trait Store)]
pub struct Pallet<T>(_);

#[pallet::storage]
pub(super) type CallIds<T: Config> = StorageMap<
_,
Blake2_128Concat,
<Blake2_128 as frame_support::StorageHasher>::Output,
mock_builder::CallId,
>;

impl<T: Config> Pallet<T> {
pub fn mock_update_investment(
f: impl Fn(&T::AccountId, T::InvestmentId, T::Amount) -> DispatchResult + 'static,
) {
register_call!(move |(a, b, c)| f(a, b, c));
}

pub fn mock_accepted_payment_currency(
f: impl Fn(T::InvestmentId, T::CurrencyId) -> bool + 'static,
) {
register_call!(move |(a, b)| f(a, b));
}

pub fn mock_investment(
f: impl Fn(&T::AccountId, T::InvestmentId) -> Result<T::Amount, DispatchError> + 'static,
) {
register_call!(move |(a, b)| f(a, b));
}

pub fn mock_update_redemption(
f: impl Fn(&T::AccountId, T::InvestmentId, T::Amount) -> DispatchResult + 'static,
) {
register_call!(move |(a, b, c)| f(a, b, c));
}

pub fn mock_accepted_payout_currency(
f: impl Fn(T::InvestmentId, T::CurrencyId) -> bool + 'static,
) {
register_call!(move |(a, b)| f(a, b));
}

pub fn mock_redemption(
f: impl Fn(&T::AccountId, T::InvestmentId) -> Result<T::Amount, DispatchError> + 'static,
) {
register_call!(move |(a, b)| f(a, b));
}

pub fn mock_collect_investment(
f: impl Fn(T::AccountId, T::InvestmentId) -> Result<(), DispatchError> + 'static,
) {
register_call!(move |(a, b)| f(a, b));
}

pub fn mock_collect_redemption(
f: impl Fn(T::AccountId, T::InvestmentId) -> Result<(), DispatchError> + 'static,
) {
register_call!(move |(a, b)| f(a, b));
}

pub fn mock_investment_requires_collect(
f: impl Fn(&T::AccountId, T::InvestmentId) -> bool + 'static,
) {
register_call!(move |(a, b)| f(a, b));
}

pub fn mock_redemption_requires_collect(
f: impl Fn(&T::AccountId, T::InvestmentId) -> bool + 'static,
) {
register_call!(move |(a, b)| f(a, b));
}
}

impl<T: Config> Investment<T::AccountId> for Pallet<T> {
type Amount = T::Amount;
type CurrencyId = T::CurrencyId;
type Error = DispatchError;
type InvestmentId = T::InvestmentId;

fn update_investment(
a: &T::AccountId,
b: Self::InvestmentId,
c: Self::Amount,
) -> DispatchResult {
execute_call!((a, b, c))
}

fn accepted_payment_currency(a: Self::InvestmentId, b: Self::CurrencyId) -> bool {
execute_call!((a, b))
}

fn investment(
a: &T::AccountId,
b: Self::InvestmentId,
) -> Result<Self::Amount, Self::Error> {
execute_call!((a, b))
}

fn update_redemption(
a: &T::AccountId,
b: Self::InvestmentId,
c: Self::Amount,
) -> DispatchResult {
execute_call!((a, b, c))
}

fn accepted_payout_currency(a: Self::InvestmentId, b: Self::CurrencyId) -> bool {
execute_call!((a, b))
}

fn redemption(
a: &T::AccountId,
b: Self::InvestmentId,
) -> Result<Self::Amount, Self::Error> {
execute_call!((a, b))
}

fn investment_requires_collect(a: &T::AccountId, b: T::InvestmentId) -> bool {
execute_call!((a, b))
}

fn redemption_requires_collect(a: &T::AccountId, b: T::InvestmentId) -> bool {
execute_call!((a, b))
}
}

impl<T: Config> InvestmentCollector<T::AccountId> for Pallet<T> {
type Error = DispatchError;
type InvestmentId = T::InvestmentId;
type Result = ();

fn collect_investment(
a: T::AccountId,
b: Self::InvestmentId,
) -> Result<Self::Result, Self::Error> {
execute_call!((a, b))
}

fn collect_redemption(
a: T::AccountId,
b: Self::InvestmentId,
) -> Result<Self::Result, Self::Error> {
execute_call!((a, b))
}
}
}
8 changes: 8 additions & 0 deletions libs/mocks/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,24 +1,32 @@
mod change_guard;
mod currency_conversion;
mod data;
mod fees;
mod investment;
mod liquidity_pools;
mod liquidity_pools_gateway_routers;
mod permissions;
mod pools;
mod rewards;
mod status_notification;
mod time;
mod token_swaps;
mod try_convert;
mod write_off_policy;

pub use change_guard::pallet_mock_change_guard;
pub use currency_conversion::pallet as pallet_mock_currency_conversion;
pub use data::pallet as pallet_mock_data;
pub use fees::pallet as pallet_mock_fees;
pub use investment::pallet as pallet_mock_investment;
pub use liquidity_pools::{pallet as pallet_mock_liquidity_pools, MessageMock};
pub use liquidity_pools_gateway_routers::{pallet as pallet_mock_routers, RouterMock};
pub use permissions::pallet as pallet_mock_permissions;
pub use pools::pallet as pallet_mock_pools;
pub use rewards::pallet as pallet_mock_rewards;
pub use status_notification::pallet as pallet_mock_status_notification;
pub use time::pallet as pallet_mock_time;
pub use token_swaps::pallet as pallet_mock_token_swaps;
pub use try_convert::pallet as pallet_mock_try_convert;
pub use write_off_policy::pallet as pallet_mock_write_off_policy;

Expand Down
40 changes: 40 additions & 0 deletions libs/mocks/src/status_notification.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#[frame_support::pallet]
pub mod pallet {
use cfg_traits::StatusNotificationHook;
use frame_support::pallet_prelude::*;
use mock_builder::{execute_call_instance, register_call_instance};

#[pallet::config]
pub trait Config<I: 'static = ()>: frame_system::Config {
type Id;
type Status;
}

#[pallet::pallet]
#[pallet::generate_store(pub(super) trait Store)]
pub struct Pallet<T, I = ()>(_);

#[pallet::storage]
pub(super) type CallIds<T: Config<I>, I: 'static = ()> = StorageMap<
_,
Blake2_128Concat,
<Blake2_128 as frame_support::StorageHasher>::Output,
mock_builder::CallId,
>;

impl<T: Config<I>, I: 'static> Pallet<T, I> {
pub fn mock_notify_status_change(f: impl Fn(T::Id, T::Status) -> DispatchResult + 'static) {
register_call_instance!(move |(a, b)| f(a, b));
}
}

impl<T: Config<I>, I: 'static> StatusNotificationHook for Pallet<T, I> {
type Error = DispatchError;
type Id = T::Id;
type Status = T::Status;

fn notify_status_change(a: Self::Id, b: Self::Status) -> DispatchResult {
execute_call_instance!((a, b))
}
}
}
Loading

0 comments on commit ccb6e2e

Please sign in to comment.