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

refactor: fungible extension test #169

Merged
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
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 {

Check warning on line 106 in extension/src/mock.rs

View workflow job for this annotation

GitHub Actions / clippy

function `new_test_ext` is never used

warning: function `new_test_ext` is never used --> extension/src/mock.rs:106:15 | 106 | pub(crate) fn new_test_ext() -> sp_io::TestExternalities { | ^^^^^^^^^^^^ | = note: `#[warn(dead_code)]` on by default
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
Loading