Skip to content

Commit

Permalink
refactor: fungible extension test (#169)
Browse files Browse the repository at this point in the history
  • Loading branch information
chungquantin committed Aug 13, 2024
1 parent 53c5983 commit f8c142d
Show file tree
Hide file tree
Showing 7 changed files with 253 additions and 137 deletions.
3 changes: 3 additions & 0 deletions Cargo.lock

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

12 changes: 10 additions & 2 deletions extension/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"]
[dependencies]
codec.workspace = true
log.workspace = true
scale-info.workspace = true

# Local
pallet-api.workspace = true
Expand All @@ -25,8 +26,10 @@ pop-runtime-common.workspace = true
frame-support.workspace = true
frame-system.workspace = true
pallet-assets.workspace = true
pallet-balances.workspace = true
pallet-contracts.workspace = true
sp-core.workspace = true
sp-io.workspace = true
sp-runtime.workspace = true
sp-std.workspace = true

Expand All @@ -36,20 +39,25 @@ rand = "0.8.5"
[features]
default = ["std"]
std = [
"log/std",
"codec/std",
"frame-support/std",
"frame-system/std",
"log/std",
"pallet-assets/std",
"pallet-balances/std",
"pallet-contracts/std",
"pop-primitives/std",
"sp-runtime/std",
"scale-info/std",
"sp-core/std",
"sp-io/std",
"sp-runtime/std",
"sp-std/std",
]
runtime-benchmarks = [
"frame-support/runtime-benchmarks",
"frame-system/runtime-benchmarks",
"pallet-assets/runtime-benchmarks",
"pallet-balances/runtime-benchmarks",
"pallet-contracts/runtime-benchmarks",
"sp-runtime/runtime-benchmarks",
]
113 changes: 4 additions & 109 deletions extension/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
#![cfg_attr(not(feature = "std"), no_std)]

pub mod constants;
mod constants;
mod mock;
#[cfg(test)]
mod tests;
mod v0;

use codec::Encode;
Expand Down Expand Up @@ -294,111 +297,3 @@ impl TryFrom<u8> for FuncId {
Ok(id)
}
}

#[cfg(test)]
mod tests {
use super::*;

// Test ensuring `func_id()` and `ext_id()` work as expected, i.e. extracting the first two
// bytes and the last two bytes, respectively, from a 4 byte array.
#[test]
fn test_byte_extraction() {
use rand::Rng;

// Helper functions
fn func_id(id: u32) -> u16 {
(id & 0x0000FFFF) as u16
}
fn ext_id(id: u32) -> u16 {
(id >> 16) as u16
}

// Number of test iterations
let test_iterations = 1_000_000;

// Create a random number generator
let mut rng = rand::thread_rng();

// Run the test for a large number of random 4-byte arrays
for _ in 0..test_iterations {
// Generate a random 4-byte array
let bytes: [u8; 4] = rng.gen();

// Convert the 4-byte array to a u32 value
let value = u32::from_le_bytes(bytes);

// Extract the first two bytes (least significant 2 bytes)
let first_two_bytes = func_id(value);

// Extract the last two bytes (most significant 2 bytes)
let last_two_bytes = ext_id(value);

// Check if the first two bytes match the expected value
assert_eq!([bytes[0], bytes[1]], first_two_bytes.to_le_bytes());

// Check if the last two bytes match the expected value
assert_eq!([bytes[2], bytes[3]], last_two_bytes.to_le_bytes());
}
}

// Test showing all the different type of variants and its encoding.
#[test]
fn encoding_of_enum() {
#[derive(Debug, PartialEq, Encode, Decode)]
enum ComprehensiveEnum {
SimpleVariant,
DataVariant(u8),
NamedFields { w: u8 },
NestedEnum(InnerEnum),
OptionVariant(Option<u8>),
VecVariant(Vec<u8>),
TupleVariant(u8, u8),
NestedStructVariant(NestedStruct),
NestedEnumStructVariant(NestedEnumStruct),
}

#[derive(Debug, PartialEq, Encode, Decode)]
enum InnerEnum {
A,
B { inner_data: u8 },
C(u8),
}

#[derive(Debug, PartialEq, Encode, Decode)]
struct NestedStruct {
x: u8,
y: u8,
}

#[derive(Debug, PartialEq, Encode, Decode)]
struct NestedEnumStruct {
inner_enum: InnerEnum,
}

// Creating each possible variant for an enum.
let enum_simple = ComprehensiveEnum::SimpleVariant;
let enum_data = ComprehensiveEnum::DataVariant(42);
let enum_named = ComprehensiveEnum::NamedFields { w: 42 };
let enum_nested = ComprehensiveEnum::NestedEnum(InnerEnum::B { inner_data: 42 });
let enum_option = ComprehensiveEnum::OptionVariant(Some(42));
let enum_vec = ComprehensiveEnum::VecVariant(vec![1, 2, 3, 4, 5]);
let enum_tuple = ComprehensiveEnum::TupleVariant(42, 42);
let enum_nested_struct =
ComprehensiveEnum::NestedStructVariant(NestedStruct { x: 42, y: 42 });
let enum_nested_enum_struct =
ComprehensiveEnum::NestedEnumStructVariant(NestedEnumStruct {
inner_enum: InnerEnum::C(42),
});

// Encode and print each variant individually to see their encoded values.
println!("{:?} -> {:?}", enum_simple, enum_simple.encode());
println!("{:?} -> {:?}", enum_data, enum_data.encode());
println!("{:?} -> {:?}", enum_named, enum_named.encode());
println!("{:?} -> {:?}", enum_nested, enum_nested.encode());
println!("{:?} -> {:?}", enum_option, enum_option.encode());
println!("{:?} -> {:?}", enum_vec, enum_vec.encode());
println!("{:?} -> {:?}", enum_tuple, enum_tuple.encode());
println!("{:?} -> {:?}", enum_nested_struct, enum_nested_struct.encode());
println!("{:?} -> {:?}", enum_nested_enum_struct, enum_nested_enum_struct.encode());
}
}
114 changes: 114 additions & 0 deletions extension/src/mock.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
#![cfg_attr(not(feature = "std"), no_std)]

use frame_support::{
derive_impl, parameter_types,
traits::{AsEnsureOriginWithArg, ConstU128, ConstU32, Everything},
};
use frame_system::{EnsureRoot, EnsureSigned};
use sp_core::H256;
use sp_runtime::{
traits::{BlakeTwo256, IdentityLookup},
BuildStorage,
};

type Block = frame_system::mocking::MockBlock<Test>;
pub(crate) type AccountId = u64;
pub(crate) type AssetId = u32;
pub(crate) type Balance = u128;

// Configure a mock runtime to test the pallet.
frame_support::construct_runtime!(
pub enum Test
{
System: frame_system = 0,
Balances: pallet_balances = 1,
Assets: pallet_assets::<Instance1> = 2,
Fungibles: pallet_api::fungibles = 150,
}
);

parameter_types! {
pub const BlockHashCount: u64 = 250;
pub const SS58Prefix: u8 = 42;
}

#[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)]
impl frame_system::Config for Test {
type BaseCallFilter = Everything;
type BlockWeights = ();
type BlockLength = ();
type RuntimeOrigin = RuntimeOrigin;
type RuntimeCall = RuntimeCall;
type Nonce = u64;
type Hash = H256;
type Hashing = BlakeTwo256;
type AccountId = AccountId;
type Lookup = IdentityLookup<Self::AccountId>;
type Block = Block;
type RuntimeEvent = RuntimeEvent;
type BlockHashCount = BlockHashCount;
type DbWeight = ();
type Version = ();
type PalletInfo = PalletInfo;
type AccountData = pallet_balances::AccountData<u128>;
type OnNewAccount = ();
type OnKilledAccount = ();
type SystemWeightInfo = ();
type SS58Prefix = SS58Prefix;
type OnSetCode = ();
type MaxConsumers = ConstU32<16>;
}

impl pallet_balances::Config for Test {
type Balance = Balance;
type DustRemoval = ();
type RuntimeEvent = RuntimeEvent;
type ExistentialDeposit = ConstU128<1>;
type AccountStore = System;
type FreezeIdentifier = ();
type MaxFreezes = ConstU32<0>;
type WeightInfo = ();
type MaxLocks = ();
type MaxReserves = ();
type ReserveIdentifier = [u8; 8];
type RuntimeHoldReason = RuntimeHoldReason;
type RuntimeFreezeReason = RuntimeFreezeReason;
}

pub(crate) type AssetsInstance = pallet_assets::Instance1;
impl pallet_assets::Config<AssetsInstance> for Test {
type RuntimeEvent = RuntimeEvent;
type Balance = Balance;
type RemoveItemsLimit = ConstU32<5>;
type AssetId = AssetId;
type AssetIdParameter = u32;
type Currency = Balances;
type CreateOrigin = AsEnsureOriginWithArg<EnsureSigned<u64>>;
type ForceOrigin = EnsureRoot<u64>;
type AssetDeposit = ConstU128<1>;
type AssetAccountDeposit = ConstU128<10>;
type MetadataDepositBase = ConstU128<1>;
type MetadataDepositPerByte = ConstU128<1>;
type ApprovalDeposit = ConstU128<1>;
type StringLimit = ConstU32<50>;
type Freezer = ();
type Extra = ();
type CallbackHandle = ();
type WeightInfo = ();
#[cfg(feature = "runtime-benchmarks")]
type BenchmarkHelper = ();
}
impl pallet_api::fungibles::Config for Test {
type AssetsInstance = AssetsInstance;
type WeightInfo = ();
}

pub(crate) fn new_test_ext() -> sp_io::TestExternalities {
let t = frame_system::GenesisConfig::<Test>::default()
.build_storage()
.expect("Frame system builds valid default genesis config");

let mut ext = sp_io::TestExternalities::new(t);
ext.execute_with(|| System::set_block_number(1));
ext
}
Original file line number Diff line number Diff line change
@@ -1,24 +1,12 @@
#[cfg(test)]
mod tests {
use crate::{config::assets::TrustBackedAssetsInstance, Assets, Runtime, System};
use codec::{Decode, Encode};
use sp_runtime::{
ArithmeticError, BuildStorage, DispatchError, ModuleError, TokenError,
MAX_MODULE_ERROR_ENCODED_SIZE,
};
use crate::mock::{new_test_ext, Assets, AssetsInstance, Test};
use codec::{Decode, Encode};
use sp_runtime::{
ArithmeticError, DispatchError, ModuleError, TokenError, MAX_MODULE_ERROR_ENCODED_SIZE,
};

fn new_test_ext() -> sp_io::TestExternalities {
let t = frame_system::GenesisConfig::<Runtime>::default()
.build_storage()
.expect("Frame system builds valid default genesis config");
let mut ext = sp_io::TestExternalities::new(t);
ext.execute_with(|| System::set_block_number(1));
ext
}

#[test]
fn encoding_decoding_dispatch_error() {
new_test_ext().execute_with(|| {
#[test]
fn encoding_decoding_dispatch_error() {
new_test_ext().execute_with(|| {
let error = DispatchError::Module(ModuleError {
index: 255,
error: [2, 0, 0, 0],
Expand All @@ -38,12 +26,12 @@ mod tests {
);

// Example pallet assets Error into ModuleError.
let index = <<Runtime as frame_system::Config>::PalletInfo as frame_support::traits::PalletInfo>::index::<
let index = <<Test as frame_system::Config>::PalletInfo as frame_support::traits::PalletInfo>::index::<
Assets,
>()
.expect("Every active module has an index in the runtime; qed") as u8;
let mut error =
pallet_assets::Error::NotFrozen::<Runtime, TrustBackedAssetsInstance>.encode();
pallet_assets::Error::NotFrozen::<Test, AssetsInstance>.encode();
error.resize(MAX_MODULE_ERROR_ENCODED_SIZE, 0);
let error = DispatchError::Module(ModuleError {
index,
Expand All @@ -52,11 +40,11 @@ mod tests {
});
let encoded = error.encode();
let decoded = DispatchError::decode(&mut &encoded[..]).unwrap();
assert_eq!(encoded, vec![3, 52, 18, 0, 0, 0]);
assert_eq!(encoded, vec![3, 2, 18, 0, 0, 0]);
assert_eq!(
decoded,
DispatchError::Module(ModuleError {
index: 52,
index: 2,
error: [18, 0, 0, 0],
message: None
})
Expand All @@ -76,5 +64,4 @@ mod tests {
assert_eq!(encoded, vec![8, 1]);
assert_eq!(decoded, error);
});
}
}
Loading

0 comments on commit f8c142d

Please sign in to comment.