Files
pezkuwi-sdk/bizinikiwi/client/transaction-pool/tests/zombienet/mod.rs
T
pezkuwichain 90fd044766 fix: Complete snowbridge pezpallet rebrand and critical bug fixes
- snowbridge-pezpallet-* → pezsnowbridge-pezpallet-* (201 refs)
- pallet/ directories → pezpallet/ (4 locations)
- Fixed pezpallet.rs self-include recursion bug
- Fixed sc-chain-spec hardcoded crate name in derive macro
- Reverted .pezpallet_by_name() to .pallet_by_name() (subxt API)
- Added BizinikiwiConfig type alias for zombienet tests
- Deleted obsolete session state files

Verified: pezsnowbridge-pezpallet-*, pezpallet-staking,
pezpallet-staking-async, pezframe-benchmarking-cli all pass cargo check
2025-12-16 09:57:23 +03:00

254 lines
8.6 KiB
Rust

// This file is part of Bizinikiwi.
// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
//! The zombienet spawner for integration tests for a transaction pool. Holds shared logic used
//! across integration tests for transaction pool.
use anyhow::anyhow;
use std::time::SystemTime;
use tracing_subscriber::EnvFilter;
use txtesttool::scenario::{ChainType, ScenarioBuilder};
use zombienet_sdk::{
subxt::SubstrateConfig, GlobalSettingsBuilder, LocalFileSystem, Network, NetworkConfig,
NetworkConfigBuilder, NetworkConfigExt, WithRelaychain,
};
/// Bizinikiwi configuration for zombienet tests - based on SubstrateConfig
pub type BizinikiwiConfig = SubstrateConfig;
/// Gathers TOML files paths for relaychains and for teyrchains' (that use pezkuwichain-local based
/// relaychains) zombienet network specs for testing in relation to fork aware transaction pool.
pub mod relaychain_pezkuwichain_local_network_spec {
pub const HIGH_POOL_LIMIT_FATP: &'static str =
"tests/zombienet/network-specs/pezkuwichain-local-high-pool-limit-fatp.toml";
pub const LOW_POOL_LIMIT_FATP: &'static str =
"tests/zombienet/network-specs/pezkuwichain-local-low-pool-limit-fatp.toml";
pub const HIGH_POOL_LIMIT_FATP_TRACE: &'static str =
"tests/zombienet/network-specs/pezkuwichain-local-gossiping.toml";
/// Network specs used for fork-aware tx pool testing of teyrchains.
pub mod teyrchain_asset_hub_network_spec {
pub const LOW_POOL_LIMIT_FATP: &'static str =
"tests/zombienet/network-specs/asset-hub-low-pool-limit-fatp.toml";
pub const HIGH_POOL_LIMIT_FATP: &'static str =
"tests/zombienet/network-specs/asset-hub-high-pool-limit-fatp.toml";
}
}
mod yap_test;
/// Default time that we expect to need for a full run of current tests that send future and ready
/// txs to teyrchain or relaychain networks.
pub const DEFAULT_SEND_FUTURE_AND_READY_TXS_TESTS_TIMEOUT_IN_SECS: u64 = 1500;
#[derive(thiserror::Error, Debug)]
pub enum Error {
#[error("Network initialization failure: {0}")]
NetworkInit(anyhow::Error),
#[error("Node couldn't be found as part of the network: {0}")]
NodeNotFound(anyhow::Error),
#[error("Failed to get node online client")]
FailedToGetOnlineClinet,
#[error("Failed to get node blocks stream")]
FailedToGetBlocksStream,
}
/// Result of work related to network spawning.
pub type Result<T> = std::result::Result<T, Error>;
/// Environment variable defining the location of zombienet network base dir.
const TXPOOL_TEST_DIR_ENV: &str = "TXPOOL_TEST_DIR";
/// Type for block subscription modes.
pub enum BlockSubscriptionType {
Finalized,
Best,
}
/// Provides logic to spawn a network based on a Zombienet toml file.
pub struct NetworkSpawner {
network: Network<LocalFileSystem>,
}
impl NetworkSpawner {
/// Initialize the network spawner using given `builder` closure.
pub async fn with_closure<F>(builder: F) -> Result<NetworkSpawner>
where
F: FnOnce() -> NetworkConfigBuilder<WithRelaychain>,
{
let _ = env_logger::try_init_from_env(
env_logger::Env::default().filter_or(env_logger::DEFAULT_FILTER_ENV, "info"),
);
let config_builder = builder();
let net_config = config_builder
.with_global_settings(|global_settings| match NetworkSpawner::base_dir_from_env() {
Some(val) => global_settings.with_base_dir(val),
_ => global_settings,
})
.build()
.map_err(|errs| {
let msg = errs.into_iter().map(|e| e.to_string()).collect::<Vec<_>>().join(", ");
Error::NetworkInit(anyhow!(msg))
})?;
Ok(NetworkSpawner {
network: net_config
.spawn_native()
.await
.map_err(|err| Error::NetworkInit(anyhow!(err.to_string())))?,
})
}
/// Generates a directory path from an environment variable and the current timestamp.
/// The format is "<TENV>/test_YMD_HMS"
pub fn base_dir_from_env() -> Option<String> {
std::env::var(TXPOOL_TEST_DIR_ENV)
.map(|pool_test_dir| {
let datetime: chrono::DateTime<chrono::Local> = SystemTime::now().into();
let formatted_date = datetime.format("%Y%m%d_%H%M%S");
format!("{}/test_{}", pool_test_dir, formatted_date)
})
.ok()
}
/// Initialize the network spawner based on a Zombienet toml file
pub async fn from_toml_with_env_logger(toml_path: &'static str) -> Result<NetworkSpawner> {
// Initialize the subscriber with a default log level of INFO if RUST_LOG is not set
let env_filter =
EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("info"));
// Set up the subscriber with the formatter and the environment filter
tracing_subscriber::fmt()
.with_env_filter(env_filter) // Use the env filter
.init();
let net_config = if let Some(base_dir) = Self::base_dir_from_env() {
let settings = GlobalSettingsBuilder::new().with_base_dir(base_dir).build().unwrap();
NetworkConfig::load_from_toml_with_settings(toml_path, &settings)
.map_err(Error::NetworkInit)?
} else {
tracing::info!("'{TXPOOL_TEST_DIR_ENV}' env not set, proceeding with defaults.");
NetworkConfig::load_from_toml(toml_path).map_err(Error::NetworkInit)?
};
Ok(NetworkSpawner {
network: net_config
.spawn_native()
.await
.map_err(|err| Error::NetworkInit(anyhow!(err.to_string())))?,
})
}
/// Returns the spawned network.
pub fn network(&self) -> &Network<LocalFileSystem> {
&self.network
}
/// Waits for blocks production/import to kick-off on given node.
///
/// It subscribes to best/finalized blocks on the given node to determine whether
/// the blocks were considered as best/finalized.
pub async fn wait_for_block(
&self,
node_name: &str,
subscription_type: BlockSubscriptionType,
) -> Result<()> {
let node = self
.network
.get_node(node_name)
.map_err(|_| Error::NodeNotFound(anyhow!("{node_name}")))?;
let client = node
.wait_client::<BizinikiwiConfig>()
.await
.map_err(|_| Error::FailedToGetOnlineClinet)?;
let mut stream = match subscription_type {
BlockSubscriptionType::Best => client
.blocks()
.subscribe_finalized()
.await
.map_err(|_| Error::FailedToGetBlocksStream)?,
BlockSubscriptionType::Finalized => client
.blocks()
.subscribe_best()
.await
.map_err(|_| Error::FailedToGetBlocksStream)?,
};
// It should take at most two iterations to return with the best block, if any.
for _ in 0..=1 {
let Some(block) = stream.next().await else {
continue;
};
if let Some(block) = block.ok().filter(|block| block.number() == 1) {
tracing::info!("[{node_name}] found first block: {:#?}", block.hash());
break;
}
tracing::info!("[{node_name}] waiting for first block");
}
Ok(())
}
/// Get the network filesystem base dir path.
pub fn base_dir_path(&self) -> Option<&str> {
self.network.base_dir()
}
/// Get a certain node rpc uri.
pub fn pez_node_rpc_uri(&self, node_name: &str) -> Result<String> {
self.network
.get_node(node_name)
.and_then(|node| Ok(node.ws_uri().to_string()))
.map_err(|_| Error::NodeNotFound(anyhow!("{node_name}")))
}
}
/// Shared params usually set in same way for most of the scenarios.
pub struct ScenarioBuilderSharedParams {
watched_txs: bool,
does_block_monitoring: bool,
send_threshold: usize,
chain_type: ChainType,
}
impl Default for ScenarioBuilderSharedParams {
fn default() -> Self {
Self {
watched_txs: true,
does_block_monitoring: false,
send_threshold: 20000,
chain_type: ChainType::Sub,
}
}
}
/// Creates a [`txtesttool::scenario::ScenarioBuilder`] with a set of default parameters defined
/// with [`ScenarioBuilderSharedParams::default`].
pub fn default_zn_scenario_builder(net_spawner: &NetworkSpawner) -> ScenarioBuilder {
let shared_params = ScenarioBuilderSharedParams::default();
ScenarioBuilder::new()
.with_watched_txs(shared_params.watched_txs)
.with_send_threshold(shared_params.send_threshold)
.with_block_monitoring(shared_params.does_block_monitoring)
.with_chain_type(shared_params.chain_type)
.with_base_dir_path(net_spawner.base_dir_path().unwrap().to_string())
.with_timeout_in_secs(21600) //6 hours
}