Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test: Add benchmarking and tests to Account follows pallet #190

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions Cargo.lock

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

16 changes: 16 additions & 0 deletions pallets/account-follows/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,26 @@ description = 'Pallet to follow/unfollow accounts'
keywords = ['blockchain', 'cryptocurrency', 'social-network', 'news-feed', 'marketplace']
categories = ['cryptography::cryptocurrencies']

[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]

[features]
default = ['std']
runtime-benchmarks = [
"frame-benchmarking/runtime-benchmarks",
"frame-system/runtime-benchmarks",
]
std = [
'codec/std',
'scale-info/std',
"frame-benchmarking/std",
'frame-support/std',
'frame-system/std',
'sp-std/std',
'pallet-profiles/std',
'subsocial-support/std',
]
try-runtime = ["frame-support/try-runtime"]

[dependencies]
codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] }
Expand All @@ -31,6 +40,13 @@ pallet-profiles = { default-features = false, path = '../profiles' }
subsocial-support = { default-features = false, path = '../support' }

# Substrate dependencies
frame-benchmarking = { optional = true, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.24", default-features = false }
frame-support = { git = 'https://github.com/paritytech/substrate', branch = 'polkadot-v0.9.24', default-features = false }
frame-system = { git = 'https://github.com/paritytech/substrate', branch = 'polkadot-v0.9.24', default-features = false }
sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.24", default-features = false }
sp-std = { git = 'https://github.com/paritytech/substrate', branch = 'polkadot-v0.9.24', default-features = false }

[dev-dependencies]
sp-io = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.24", default-features = false }
sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.24", default-features = false }
smallvec = "1.6.1"
66 changes: 66 additions & 0 deletions pallets/account-follows/src/benchmarking.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
#![cfg(feature = "runtime-benchmarks")]

use frame_benchmarking::{account, benchmarks};
use frame_support::ensure;
use frame_system::RawOrigin;

use crate as pallet_account_follows;

use super::*;

benchmarks! {
follow_account {
let follower: T::AccountId = account("follower", 0, 0);
let followee: T::AccountId = account("followee", 1, 1);

let follower_origin = RawOrigin::Signed(follower.clone());

}: _(follower_origin, followee.clone())
verify {
ensure!(
AccountsFollowedByAccount::<T>::get(follower.clone()).contains(&followee),
"AccountsFollowedByAccount didn't get updated",
);
ensure!(
AccountFollowers::<T>::get(followee.clone()).contains(&follower),
"AccountFollowers didn't get updated",
);
ensure!(
AccountFollowedByAccount::<T>::get((follower.clone(), followee.clone())),
"AccountFollowedByAccount didn't get updated",
);
}

unfollow_account {
let follower: T::AccountId = account("follower", 0, 0);
let followee: T::AccountId = account("followee", 1, 1);

let follower_origin = RawOrigin::Signed(follower.clone());

ensure!(pallet_account_follows::Pallet::<T>::follow_account(
follower_origin.clone().into(),
followee.clone(),
).is_ok(), "follow_account call returned an err");

}: _(follower_origin, followee.clone())
verify {
ensure!(
!AccountsFollowedByAccount::<T>::get(follower.clone()).contains(&followee),
"AccountsFollowedByAccount didn't get updated",
);
ensure!(
!AccountFollowers::<T>::get(followee.clone()).contains(&follower),
"AccountFollowers didn't get updated",
);
ensure!(
!AccountFollowedByAccount::<T>::get((follower.clone(), followee.clone())),
"AccountFollowedByAccount didn't get updated",
);
}

impl_benchmark_test_suite!(
Pallet,
crate::mock::ExtBuilder::build(),
crate::mock::TestRuntime,
);
}
19 changes: 17 additions & 2 deletions pallets/account-follows/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,24 @@
#![cfg_attr(not(feature = "std"), no_std)]

#[cfg(test)]
mod mock;

#[cfg(test)]
mod tests;

#[cfg(feature = "runtime-benchmarks")]
mod benchmarking;

pub use pallet::*;

pub mod weights;

// pub mod rpc;

#[frame_support::pallet]
pub mod pallet {
use super::*;
use crate::weights::WeightInfo;
use frame_support::pallet_prelude::*;
use frame_system::pallet_prelude::*;

Expand All @@ -19,6 +31,9 @@ pub mod pallet {
pub trait Config: frame_system::Config {
/// The overarching event type.
type Event: From<Event<Self>> + IsType<<Self as frame_system::Config>::Event>;

/// Weight information for extrinsics in this pallet.
type WeightInfo: WeightInfo;
}

#[pallet::pallet]
Expand Down Expand Up @@ -68,7 +83,7 @@ pub mod pallet {

#[pallet::call]
impl<T: Config> Pallet<T> {
#[pallet::weight(1_250_000 + T::DbWeight::get().reads_writes(2, 3))]
#[pallet::weight(< T as Config >::WeightInfo::follow_account())]
pub fn follow_account(origin: OriginFor<T>, account: T::AccountId) -> DispatchResult {
let follower = ensure_signed(origin)?;

Expand All @@ -88,7 +103,7 @@ pub mod pallet {
Ok(())
}

#[pallet::weight(1_250_000 + T::DbWeight::get().reads_writes(2, 3))]
#[pallet::weight(< T as Config >::WeightInfo::unfollow_account())]
pub fn unfollow_account(origin: OriginFor<T>, account: T::AccountId) -> DispatchResult {
let follower = ensure_signed(origin)?;

Expand Down
73 changes: 73 additions & 0 deletions pallets/account-follows/src/mock.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
use frame_support::traits::{ConstU32, ConstU64};
use sp_core::H256;
use sp_io::TestExternalities;
use sp_runtime::{
testing::Header,
traits::{BlakeTwo256, IdentityLookup},
};

use crate as pallet_account_follows;

type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic<TestRuntime>;
type Block = frame_system::mocking::MockBlock<TestRuntime>;
pub(super) type AccountId = u64;
type BlockNumber = u64;

frame_support::construct_runtime!(
pub enum TestRuntime where
Block = Block,
NodeBlock = Block,
UncheckedExtrinsic = UncheckedExtrinsic,
{
System: frame_system,
AccountFollows: pallet_account_follows,
}
);

impl frame_system::Config for TestRuntime {
type BaseCallFilter = frame_support::traits::Everything;
type BlockWeights = ();
type BlockLength = ();
type Origin = Origin;
type Call = Call;
type Index = u64;
type BlockNumber = BlockNumber;
type Hash = H256;
type Hashing = BlakeTwo256;
type AccountId = AccountId;
type Lookup = IdentityLookup<Self::AccountId>;
type Header = Header;
type Event = Event;
type BlockHashCount = ConstU64<250>;
type DbWeight = ();
type Version = ();
type PalletInfo = PalletInfo;
type AccountData = ();
type OnNewAccount = ();
type OnKilledAccount = ();
type SystemWeightInfo = ();
type SS58Prefix = ();
type OnSetCode = ();
type MaxConsumers = ConstU32<16>;
}

impl pallet_account_follows::Config for TestRuntime {
type Event = Event;
type WeightInfo = ();
}

pub struct ExtBuilder;

impl ExtBuilder {
pub(crate) fn build() -> TestExternalities {
let storage =
&mut frame_system::GenesisConfig::default().build_storage::<TestRuntime>().unwrap();

let mut ext = TestExternalities::from(storage.clone());
ext.execute_with(|| {
System::set_block_number(1);
});

ext
}
}
95 changes: 95 additions & 0 deletions pallets/account-follows/src/tests.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
use frame_support::{assert_noop, assert_ok};

use crate::{mock::*, pallet::*, Error, Event};

#[test]
fn follow_account_should_fail_if_account_tries_to_follow_himself() {
ExtBuilder::build().execute_with(|| {
let account = 1;
assert_noop!(
AccountFollows::follow_account(Origin::signed(account), account),
Error::<TestRuntime>::AccountCannotFollowItself,
);
});
}

#[test]
fn follow_account_should_fail_if_already_a_follower() {
ExtBuilder::build().execute_with(|| {
let follower = 1;
let followee = 2;

assert_ok!(AccountFollows::follow_account(Origin::signed(follower), followee));

assert_noop!(
AccountFollows::follow_account(Origin::signed(follower), followee),
Error::<TestRuntime>::AlreadyAccountFollower,
);
});
}

#[test]
fn follow_account_should_work() {
ExtBuilder::build().execute_with(|| {
let follower = 1;
let followee = 2;

assert_ok!(AccountFollows::follow_account(Origin::signed(follower), followee));

assert!(AccountsFollowedByAccount::<TestRuntime>::get(follower.clone()).contains(&followee));
assert!(AccountFollowers::<TestRuntime>::get(followee.clone()).contains(&follower));
assert!(AccountFollowedByAccount::<TestRuntime>::get((follower.clone(), followee.clone())));

System::assert_last_event(Event::AccountFollowed {
follower,
account: followee,
}.into());
});
}

#[test]
fn unfollow_account_should_fail_if_account_tries_to_unfollow_himself() {
ExtBuilder::build().execute_with(|| {
let account = 1;
assert_noop!(
AccountFollows::unfollow_account(Origin::signed(account), account),
Error::<TestRuntime>::AccountCannotUnfollowItself,
);
});
}

#[test]
fn unfollow_account_should_fail_if_account_not_a_follower() {
ExtBuilder::build().execute_with(|| {
let follower = 1;
let followee = 2;

assert_noop!(
AccountFollows::unfollow_account(Origin::signed(follower), followee),
Error::<TestRuntime>::NotAccountFollower,
);
});
}

#[test]
fn unfollow_account_should_work() {
ExtBuilder::build().execute_with(|| {
let follower = 1;
let followee = 2;

assert_ok!(AccountFollows::follow_account(Origin::signed(follower), followee));

assert_ok!(AccountFollows::unfollow_account(Origin::signed(follower), followee));

assert!(
!AccountsFollowedByAccount::<TestRuntime>::get(follower.clone()).contains(&followee)
);
assert!(!AccountFollowers::<TestRuntime>::get(followee.clone()).contains(&follower));
assert!(!AccountFollowedByAccount::<TestRuntime>::get((
follower.clone(),
followee.clone()
)));

System::assert_last_event(Event::AccountUnfollowed { follower, account: followee }.into());
});
}
Loading