pub mod zombienet;
use std::time::Duration;
use crate::zombienet::{
default_zn_scenario_builder, relaychain_rococo_local_network_spec as relay,
relaychain_rococo_local_network_spec::parachain_asset_hub_network_spec as para,
BlockSubscriptionType, NetworkSpawner,
};
use futures::future::join_all;
use tracing::info;
use txtesttool::{execution_log::ExecutionLog, scenario::ScenarioExecutor};
use zombienet::DEFAULT_SEND_FUTURE_AND_READY_TXS_TESTS_TIMEOUT_IN_SECS;
#[tokio::test(flavor = "multi_thread")]
#[ignore]
async fn send_future_and_ready_from_many_accounts_to_parachain() {
let net = NetworkSpawner::from_toml_with_env_logger(para::HIGH_POOL_LIMIT_FATP)
.await
.unwrap();
net.wait_for_block("charlie", BlockSubscriptionType::Best).await.unwrap();
let ws = net.node_rpc_uri("charlie").unwrap();
let future_scenario_executor = default_zn_scenario_builder(&net)
.with_rpc_uri(ws.clone())
.with_start_id(0)
.with_last_id(99)
.with_nonce_from(Some(100))
.with_txs_count(100)
.with_executor_id("future-txs-executor".to_string())
.with_timeout_in_secs(DEFAULT_SEND_FUTURE_AND_READY_TXS_TESTS_TIMEOUT_IN_SECS)
.build()
.await;
let ready_scenario_executor = default_zn_scenario_builder(&net)
.with_rpc_uri(ws)
.with_start_id(0)
.with_last_id(99)
.with_nonce_from(Some(0))
.with_txs_count(100)
.with_executor_id("ready-txs-executor".to_string())
.with_timeout_in_secs(DEFAULT_SEND_FUTURE_AND_READY_TXS_TESTS_TIMEOUT_IN_SECS)
.build()
.await;
let (future_logs, ready_logs) = futures::future::join(
future_scenario_executor.execute(),
ready_scenario_executor.execute(),
)
.await;
let finalized_future =
future_logs.values().filter_map(|default_log| default_log.finalized()).count();
let finalized_ready =
ready_logs.values().filter_map(|default_log| default_log.finalized()).count();
assert_eq!(finalized_future, 10_000);
assert_eq!(finalized_ready, 10_000);
}
#[tokio::test(flavor = "multi_thread")]
#[ignore]
async fn send_future_and_ready_from_many_accounts_to_relaychain() {
let net = NetworkSpawner::from_toml_with_env_logger(relay::HIGH_POOL_LIMIT_FATP)
.await
.unwrap();
net.wait_for_block("alice", BlockSubscriptionType::Best).await.unwrap();
let ws = net.node_rpc_uri("alice").unwrap();
let future_scenario_executor = default_zn_scenario_builder(&net)
.with_rpc_uri(ws.clone())
.with_start_id(0)
.with_last_id(99)
.with_nonce_from(Some(100))
.with_txs_count(100)
.with_executor_id("future-txs-executor".to_string())
.with_timeout_in_secs(DEFAULT_SEND_FUTURE_AND_READY_TXS_TESTS_TIMEOUT_IN_SECS)
.build()
.await;
let ready_scenario_executor = default_zn_scenario_builder(&net)
.with_rpc_uri(ws)
.with_start_id(0)
.with_last_id(99)
.with_nonce_from(Some(0))
.with_txs_count(100)
.with_executor_id("ready-txs-executor".to_string())
.with_timeout_in_secs(DEFAULT_SEND_FUTURE_AND_READY_TXS_TESTS_TIMEOUT_IN_SECS)
.build()
.await;
let (future_logs, ready_logs) = futures::future::join(
future_scenario_executor.execute(),
ready_scenario_executor.execute(),
)
.await;
let finalized_future =
future_logs.values().filter_map(|default_log| default_log.finalized()).count();
let finalized_ready =
ready_logs.values().filter_map(|default_log| default_log.finalized()).count();
assert_eq!(finalized_future, 10_000);
assert_eq!(finalized_ready, 10_000);
}
#[tokio::test(flavor = "multi_thread")]
#[ignore]
async fn send_future_mortal_txs() {
let net = NetworkSpawner::from_toml_with_env_logger(relay::HIGH_POOL_LIMIT_FATP)
.await
.unwrap();
net.wait_for_block("alice", BlockSubscriptionType::Finalized).await.unwrap();
let ws = net.node_rpc_uri("alice").unwrap();
let ready_scenario_executor = default_zn_scenario_builder(&net)
.with_rpc_uri(ws.clone())
.with_start_id(0)
.with_nonce_from(Some(0))
.with_txs_count(50)
.with_remark_recipe(750)
.with_executor_id("ready-txs-executor".to_string())
.build()
.await;
let mortal_scenario_invalid = default_zn_scenario_builder(&net)
.with_rpc_uri(ws.clone())
.with_start_id(0)
.with_nonce_from(Some(60))
.with_txs_count(10)
.with_executor_id("mortal-tx-executor-invalid".to_string())
.with_mortality(5)
.build()
.await;
let mortal_scenario_success = default_zn_scenario_builder(&net)
.with_rpc_uri(ws)
.with_start_id(0)
.with_nonce_from(Some(50))
.with_txs_count(10)
.with_executor_id("mortal-tx-executor-success".to_string())
.with_mortality(25)
.build()
.await;
let (mortal_invalid_logs, ready_logs, mortal_succes_logs) = tokio::join!(
mortal_scenario_invalid.execute(),
ready_scenario_executor.execute(),
mortal_scenario_success.execute(),
);
let mortal_invalid = mortal_invalid_logs
.values()
.filter(|default_log| default_log.get_invalid_reason().len() > 0)
.count();
let mortal_succesfull = mortal_succes_logs
.values()
.filter_map(|default_log| default_log.finalized())
.count();
let finalized_ready =
ready_logs.values().filter_map(|default_log| default_log.finalized()).count();
assert_eq!(mortal_invalid, 10);
assert_eq!(mortal_succesfull, 10);
assert_eq!(finalized_ready, 50);
}
#[tokio::test(flavor = "multi_thread")]
#[ignore]
async fn send_lower_priority_mortal_txs() {
let net = NetworkSpawner::from_toml_with_env_logger(relay::HIGH_POOL_LIMIT_FATP)
.await
.unwrap();
net.wait_for_block("alice", BlockSubscriptionType::Finalized).await.unwrap();
let ws = net.node_rpc_uri("alice").unwrap();
let ready_scenario_executor = default_zn_scenario_builder(&net)
.with_rpc_uri(ws.clone())
.with_start_id(0)
.with_nonce_from(Some(0))
.with_txs_count(50)
.with_executor_id("ready-txs-executor".to_string())
.with_remark_recipe(750)
.with_tip(150)
.build()
.await;
let mortal_scenario_invalid = default_zn_scenario_builder(&net)
.with_rpc_uri(ws.clone())
.with_start_id(1)
.with_nonce_from(Some(0))
.with_txs_count(10)
.with_executor_id("mortal-tx-executor-invalid".to_string())
.with_mortality(5)
.with_remark_recipe(3500)
.with_tip(50)
.build()
.await;
let mortal_scenario_success = default_zn_scenario_builder(&net)
.with_rpc_uri(ws)
.with_start_id(2)
.with_nonce_from(Some(0))
.with_txs_count(10)
.with_executor_id("mortal-tx-executor-success".to_string())
.with_mortality(20)
.with_remark_recipe(750)
.with_tip(100)
.build()
.await;
let (mortal_invalid_logs, ready_logs, mortal_success_logs) = tokio::join!(
mortal_scenario_invalid.execute(),
ready_scenario_executor.execute(),
mortal_scenario_success.execute(),
);
let mortal_invalid = mortal_invalid_logs
.values()
.filter(|default_log| default_log.get_invalid_reason().len() > 0)
.count();
let mortal_succesfull = mortal_success_logs
.values()
.filter_map(|default_log| default_log.finalized())
.count();
let finalized_ready =
ready_logs.values().filter_map(|default_log| default_log.finalized()).count();
assert_eq!(mortal_invalid, 10);
assert_eq!(mortal_succesfull, 10);
assert_eq!(finalized_ready, 50);
}
#[tokio::test(flavor = "multi_thread")]
#[ignore]
async fn send_5m_from_many_accounts_to_parachain() {
let net = NetworkSpawner::from_toml_with_env_logger(para::HIGH_POOL_LIMIT_FATP)
.await
.unwrap();
net.wait_for_block("charlie", BlockSubscriptionType::Best).await.unwrap();
let ws = net.node_rpc_uri("charlie").unwrap();
let executor = default_zn_scenario_builder(&net)
.with_rpc_uri(ws)
.with_start_id(0)
.with_last_id(999)
.with_txs_count(5_000)
.with_executor_id("txs-executor".to_string())
.with_send_threshold(7500)
.build()
.await;
let execution_logs = executor.execute().await;
let finalized_txs = execution_logs.values().filter_map(|tx_log| tx_log.finalized()).count();
assert_eq!(finalized_txs, 5_000_000);
}
#[tokio::test(flavor = "multi_thread")]
#[ignore]
async fn send_5m_from_many_accounts_to_relaychain() {
let net = NetworkSpawner::from_toml_with_env_logger(relay::HIGH_POOL_LIMIT_FATP)
.await
.unwrap();
net.wait_for_block("alice", BlockSubscriptionType::Best).await.unwrap();
let ws = net.node_rpc_uri("alice").unwrap();
let executor = default_zn_scenario_builder(&net)
.with_rpc_uri(ws.clone())
.with_start_id(0)
.with_last_id(999)
.with_txs_count(5000)
.with_executor_id("txs-executor".to_string())
.with_send_threshold(7500)
.build()
.await;
let execution_logs = executor.execute().await;
let finalized_txs = execution_logs.values().filter_map(|tx_log| tx_log.finalized()).count();
assert_eq!(finalized_txs, 5_000_000);
}
#[tokio::test(flavor = "multi_thread")]
#[ignore]
async fn gossiping() {
let net = NetworkSpawner::from_toml_with_env_logger(relay::HIGH_POOL_LIMIT_FATP_TRACE)
.await
.unwrap();
net.wait_for_block("a00", BlockSubscriptionType::Best).await.unwrap();
let ws = net.node_rpc_uri("a00").unwrap();
let executor = default_zn_scenario_builder(&net)
.with_rpc_uri(ws)
.with_start_id(0)
.with_last_id(999)
.with_executor_id("txs-executor".to_string())
.build()
.await;
let execution_logs = executor.execute().await;
let finalized_txs = execution_logs.values().filter_map(|tx_log| tx_log.finalized()).count();
assert_eq!(finalized_txs, 1000);
tracing::info!("BASEDIR: {:?}", net.base_dir_path());
}
async fn send_batch(
net: &NetworkSpawner,
node_name: &str,
from: u32,
to: u32,
prio: u32,
) -> ScenarioExecutor {
let ws = net.node_rpc_uri(node_name).unwrap();
info!(from, to, prio, "send_batch");
default_zn_scenario_builder(net)
.with_rpc_uri(ws)
.with_start_id(from)
.with_last_id(to)
.with_txs_count(1)
.with_tip(prio.into())
.with_executor_id(format!("txs-executor_{}_{}_{}", from, to, prio))
.with_send_threshold(usize::MAX)
.with_legacy_backend(true)
.build()
.await
}
async fn batch_loop<F>(
net: &NetworkSpawner,
node_name: &str,
from: u32,
to: u32,
priority: F,
period: std::time::Duration,
) where
F: Fn(u32) -> u32,
{
let mut prio = 0;
loop {
prio = priority(prio);
let executor = send_batch(&net, node_name, from, to, prio).await;
let start = std::time::Instant::now();
let _results = tokio::time::timeout(period, executor.execute()).await;
let elapsed = start.elapsed();
if elapsed < period {
tokio::time::sleep(period - elapsed).await;
}
}
}
#[tokio::test(flavor = "multi_thread")]
#[ignore]
async fn test_limits_increasing_prio_parachain() {
let net = NetworkSpawner::from_toml_with_env_logger(para::LOW_POOL_LIMIT_FATP)
.await
.unwrap();
net.wait_for_block("charlie", BlockSubscriptionType::Best).await.unwrap();
let mut executors = vec![];
let senders_count = 25;
let sender_batch = 2000;
for i in 0..senders_count {
let from = 0 + i * sender_batch;
let to = from + sender_batch - 1;
executors.push(batch_loop(
&net,
"charlie",
from,
to,
|prio| prio + 1,
Duration::from_secs(60),
));
}
let _results = join_all(executors).await;
}
#[tokio::test(flavor = "multi_thread")]
#[ignore]
async fn test_limits_increasing_prio_relaychain() {
let net = NetworkSpawner::from_toml_with_env_logger(relay::LOW_POOL_LIMIT_FATP)
.await
.unwrap();
net.wait_for_block("alice", BlockSubscriptionType::Best).await.unwrap();
let mut executors = vec![];
let senders_count = 50;
let sender_batch = 2000;
for i in 0..senders_count {
let from = 0 + i * sender_batch;
let to = from + sender_batch - 1;
executors.push(batch_loop(
&net,
"alice",
from,
to,
|prio| prio + 1,
Duration::from_secs(15),
));
}
let _results = join_all(executors).await;
}
#[tokio::test(flavor = "multi_thread")]
#[ignore]
async fn test_limits_same_prio_relaychain() {
let net = NetworkSpawner::from_toml_with_env_logger(relay::LOW_POOL_LIMIT_FATP)
.await
.unwrap();
net.wait_for_block("alice", BlockSubscriptionType::Best).await.unwrap();
let mut executors = vec![];
let senders_count = 50;
let sender_batch = 2000;
for i in 0..senders_count {
let from = 0 + i * sender_batch;
let to = from + sender_batch - 1;
executors.push(batch_loop(&net, "alice", from, to, |prio| prio, Duration::from_secs(15)));
}
let _results = join_all(executors).await;
}