From 651ca808a65c9d0527b9b7fcb93944d1c1598f82 Mon Sep 17 00:00:00 2001 From: Raid Ateir Date: Thu, 9 Nov 2023 19:20:46 +0100 Subject: [PATCH] add tests for ddc-node --- pallets/ddc-nodes/Cargo.toml | 2 + pallets/ddc-nodes/src/lib.rs | 5 + pallets/ddc-nodes/src/mock.rs | 114 ++++++++++++++++++++ pallets/ddc-nodes/src/tests.rs | 183 +++++++++++++++++++++++++++++++++ 4 files changed, 304 insertions(+) create mode 100644 pallets/ddc-nodes/src/mock.rs create mode 100644 pallets/ddc-nodes/src/tests.rs diff --git a/pallets/ddc-nodes/Cargo.toml b/pallets/ddc-nodes/Cargo.toml index 607ab47fa..f3cc63163 100644 --- a/pallets/ddc-nodes/Cargo.toml +++ b/pallets/ddc-nodes/Cargo.toml @@ -18,6 +18,8 @@ sp-std = { version = "4.0.0-dev", default-features = false, git = "https://githu sp-core = { version = "6.0.0", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.30", default-features = false } [dev-dependencies] +pallet-balances = { version = "4.0.0-dev", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.30" } +pallet-timestamp = { version = "4.0.0-dev", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.30" } sp-core = { version = "6.0.0", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.30" } sp-tracing = { version = "5.0.0", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.30" } substrate-test-utils = { version = "4.0.0-dev", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.30" } diff --git a/pallets/ddc-nodes/src/lib.rs b/pallets/ddc-nodes/src/lib.rs index f0e881f7f..5dc0766ce 100644 --- a/pallets/ddc-nodes/src/lib.rs +++ b/pallets/ddc-nodes/src/lib.rs @@ -14,6 +14,11 @@ #![cfg_attr(not(feature = "std"), no_std)] #![recursion_limit = "256"] +#[cfg(test)] +pub(crate) mod mock; +#[cfg(test)] +mod tests; + use ddc_primitives::{CDNNodePubKey, ClusterId, NodePubKey, StorageNodePubKey}; use frame_support::pallet_prelude::*; use frame_system::pallet_prelude::*; diff --git a/pallets/ddc-nodes/src/mock.rs b/pallets/ddc-nodes/src/mock.rs new file mode 100644 index 000000000..8a8002c0c --- /dev/null +++ b/pallets/ddc-nodes/src/mock.rs @@ -0,0 +1,114 @@ +//! Test utilities + +#![allow(dead_code)] + +use crate::{self as pallet_ddc_nodes, *}; +use frame_support::{ + construct_runtime, parameter_types, + traits::{ConstU32, ConstU64, Everything}, + weights::constants::RocksDbWeight, +}; +use frame_system::mocking::{MockBlock, MockUncheckedExtrinsic}; +use sp_core::H256; +use sp_io::TestExternalities; +use sp_runtime::{ + testing::Header, + traits::{BlakeTwo256, IdentityLookup}, +}; + +/// The AccountId alias in this test module. +pub(crate) type AccountId = u64; +pub(crate) type AccountIndex = u64; +pub(crate) type BlockNumber = u64; +pub(crate) type Balance = u128; + +type UncheckedExtrinsic = MockUncheckedExtrinsic; +type Block = MockBlock; + +construct_runtime!( + pub enum Test where + Block = Block, + NodeBlock = Block, + UncheckedExtrinsic = UncheckedExtrinsic, + { + System: frame_system::{Pallet, Call, Config, Storage, Event}, + Timestamp: pallet_timestamp::{Pallet, Call, Storage, Inherent}, + Balances: pallet_balances::{Pallet, Call, Storage, Config, Event}, + DdcNodes: pallet_ddc_nodes::{Pallet, Call, Storage, Event}, + } +); + +parameter_types! { + pub static ExistentialDeposit: Balance = 1; +} + +impl frame_system::Config for Test { + type BaseCallFilter = Everything; + type BlockWeights = (); + type BlockLength = (); + type DbWeight = RocksDbWeight; + type RuntimeOrigin = RuntimeOrigin; + type Index = AccountIndex; + type BlockNumber = BlockNumber; + type RuntimeCall = RuntimeCall; + type Hash = H256; + type Hashing = BlakeTwo256; + type AccountId = AccountId; + type Lookup = IdentityLookup; + type Header = Header; + type RuntimeEvent = RuntimeEvent; + type BlockHashCount = ConstU64<250>; + type Version = (); + type PalletInfo = PalletInfo; + type AccountData = pallet_balances::AccountData; + type OnNewAccount = (); + type OnKilledAccount = (); + type SystemWeightInfo = (); + type SS58Prefix = (); + type OnSetCode = (); + type MaxConsumers = ConstU32<16>; +} + +impl pallet_balances::Config for Test { + type MaxLocks = ConstU32<1024>; + type MaxReserves = (); + type ReserveIdentifier = [u8; 8]; + type Balance = Balance; + type RuntimeEvent = RuntimeEvent; + type DustRemoval = (); + type ExistentialDeposit = ExistentialDeposit; + type AccountStore = System; + type WeightInfo = (); +} + +impl pallet_timestamp::Config for Test { + type Moment = u64; + type OnTimestampSet = (); + type MinimumPeriod = ConstU64<5>; + type WeightInfo = (); +} + +impl crate::pallet::Config for Test { + type RuntimeEvent = RuntimeEvent; +} + +pub(crate) type TestRuntimeCall = ::RuntimeCall; + +pub struct ExtBuilder; + +impl ExtBuilder { + fn build(self) -> TestExternalities { + sp_tracing::try_init_simple(); + let mut storage = frame_system::GenesisConfig::default().build_storage::().unwrap(); + + let _ = pallet_balances::GenesisConfig:: { balances: vec![(1, 100), (2, 100)] } + .assimilate_storage(&mut storage); + + TestExternalities::new(storage) + } + pub fn build_and_execute(self, test: impl FnOnce() -> ()) { + sp_tracing::try_init_simple(); + let mut ext = self.build(); + ext.execute_with(test); + } +} diff --git a/pallets/ddc-nodes/src/tests.rs b/pallets/ddc-nodes/src/tests.rs new file mode 100644 index 000000000..9cbdc526c --- /dev/null +++ b/pallets/ddc-nodes/src/tests.rs @@ -0,0 +1,183 @@ +//! Tests for the module. + +use super::{mock::*, *}; +use crate::{cdn_node::CDNNodeParams, storage_node::StorageNodeParams}; +use ddc_primitives::NodePubKey; +use frame_support::{assert_noop, assert_ok}; +use sp_runtime::AccountId32; + +#[test] +fn create_node_works() { + ExtBuilder.build_and_execute(|| { + System::set_block_number(1); + let bytes = [0u8; 32]; + let node_pub_key = AccountId32::from(bytes); + let cdn_node_params = CDNNodeParams { + host: vec![1u8, 255], + http_port: 35000u16, + grpc_port: 25000u16, + p2p_port: 15000u16, + }; + + // Node params are not valid + assert_noop!( + DdcNodes::create_node( + RuntimeOrigin::signed(1), + NodePubKey::CDNPubKey(node_pub_key.clone()), + NodeParams::StorageParams(StorageNodeParams { + host: vec![1u8, 255], + http_port: 35000u16, + grpc_port: 25000u16, + p2p_port: 15000u16, + }) + ), + Error::::InvalidNodeParams + ); + + // Node created + assert_ok!(DdcNodes::create_node( + RuntimeOrigin::signed(1), + NodePubKey::CDNPubKey(node_pub_key.clone()), + NodeParams::CDNParams(cdn_node_params.clone()) + )); + + // Node already exists + assert_noop!( + DdcNodes::create_node( + RuntimeOrigin::signed(1), + NodePubKey::CDNPubKey(node_pub_key.clone()), + NodeParams::CDNParams(cdn_node_params) + ), + Error::::NodeAlreadyExists + ); + + // Checking that event was emitted + assert_eq!(System::events().len(), 1); + System::assert_last_event( + Event::NodeCreated { node_pub_key: NodePubKey::CDNPubKey(node_pub_key) }.into(), + ) + }) +} + +#[test] +fn set_node_params_works() { + ExtBuilder.build_and_execute(|| { + System::set_block_number(1); + let bytes = [0u8; 32]; + let node_pub_key = AccountId32::from(bytes); + let storage_node_params = StorageNodeParams { + host: vec![1u8, 255], + http_port: 35000u16, + grpc_port: 25000u16, + p2p_port: 15000u16, + }; + let cdn_node_params = CDNNodeParams { + host: vec![1u8, 255], + http_port: 35000u16, + grpc_port: 25000u16, + p2p_port: 15000u16, + }; + + // Node doesn't exist + assert_noop!( + DdcNodes::set_node_params( + RuntimeOrigin::signed(1), + NodePubKey::CDNPubKey(node_pub_key.clone()), + NodeParams::CDNParams(cdn_node_params.clone()) + ), + Error::::NodeDoesNotExist + ); + + // Node created + assert_ok!(DdcNodes::create_node( + RuntimeOrigin::signed(1), + NodePubKey::CDNPubKey(node_pub_key.clone()), + NodeParams::CDNParams(cdn_node_params.clone()) + )); + + // Set node params + assert_ok!(DdcNodes::set_node_params( + RuntimeOrigin::signed(1), + NodePubKey::CDNPubKey(node_pub_key.clone()), + NodeParams::CDNParams(cdn_node_params.clone()) + )); + + // Node params are not valid + assert_noop!( + DdcNodes::set_node_params( + RuntimeOrigin::signed(1), + NodePubKey::CDNPubKey(node_pub_key.clone()), + NodeParams::StorageParams(storage_node_params) + ), + Error::::InvalidNodeParams + ); + + // Only node provider can set params + assert_noop!( + DdcNodes::set_node_params( + RuntimeOrigin::signed(2), + NodePubKey::CDNPubKey(node_pub_key.clone()), + NodeParams::CDNParams(cdn_node_params.clone()) + ), + Error::::OnlyNodeProvider + ); + + // Checking that event was emitted + assert_eq!(System::events().len(), 2); + System::assert_last_event( + Event::NodeParamsChanged { node_pub_key: NodePubKey::CDNPubKey(node_pub_key) }.into(), + ) + }) +} + +#[test] +fn set_delete_node_works() { + ExtBuilder.build_and_execute(|| { + System::set_block_number(1); + let bytes = [0u8; 32]; + let node_pub_key = AccountId32::from(bytes); + let cdn_node_params = CDNNodeParams { + host: vec![1u8, 255], + http_port: 35000u16, + grpc_port: 25000u16, + p2p_port: 15000u16, + }; + + // Node doesn't exist + assert_noop!( + DdcNodes::delete_node( + RuntimeOrigin::signed(1), + NodePubKey::CDNPubKey(node_pub_key.clone()) + ), + Error::::NodeDoesNotExist + ); + + // Create node + assert_ok!(DdcNodes::create_node( + RuntimeOrigin::signed(1), + NodePubKey::CDNPubKey(node_pub_key.clone()), + NodeParams::CDNParams(cdn_node_params.clone()) + )); + + // Only node provider can delete + assert_noop!( + DdcNodes::delete_node( + RuntimeOrigin::signed(2), + NodePubKey::CDNPubKey(node_pub_key.clone()) + ), + Error::::OnlyNodeProvider + ); + + // Delete node + assert_ok!(DdcNodes::delete_node( + RuntimeOrigin::signed(1), + NodePubKey::CDNPubKey(node_pub_key.clone()), + )); + + // Checking that event was emitted + assert_eq!(System::events().len(), 2); + System::assert_last_event( + Event::NodeDeleted { node_pub_key: NodePubKey::CDNPubKey(node_pub_key) }.into(), + ) + }) +}