diff --git a/testsuite/forge-cli/src/main.rs b/testsuite/forge-cli/src/main.rs index 88abed486a8448..addfeceec3b53e 100644 --- a/testsuite/forge-cli/src/main.rs +++ b/testsuite/forge-cli/src/main.rs @@ -62,6 +62,7 @@ use clap::{Parser, Subcommand}; use futures::stream::{FuturesUnordered, StreamExt}; use once_cell::sync::Lazy; use rand::{rngs::ThreadRng, seq::SliceRandom, Rng}; +use suites::dag::get_dag_test; use std::{ env, num::NonZeroUsize, @@ -77,6 +78,8 @@ use std::{ use tokio::{runtime::Runtime, select}; use url::Url; +mod suites; + // Useful constants const KILOBYTE: usize = 1000; const MEGABYTE: usize = KILOBYTE * 1000; @@ -518,6 +521,8 @@ fn get_test_suite( return Ok(test_suite); } else if let Some(test_suite) = get_state_sync_test(test_name) { return Ok(test_suite); + } else if let Some(test_suite) = get_dag_test(test_name, duration, test_cmd) { + return Ok(test_suite) } // Otherwise, check the test name against the ungrouped test suites diff --git a/testsuite/forge-cli/src/suites/dag.rs b/testsuite/forge-cli/src/suites/dag.rs new file mode 100644 index 00000000000000..8c9072a163341b --- /dev/null +++ b/testsuite/forge-cli/src/suites/dag.rs @@ -0,0 +1,105 @@ +use crate::{wrap_with_realistic_env, TestCommand}; +use aptos_forge::{success_criteria::{LatencyType, StateProgressThreshold, SuccessCriteria}, EmitJobMode, EmitJobRequest, ForgeConfig}; +use aptos_sdk::types::on_chain_config::{ + ConsensusAlgorithmConfig, DagConsensusConfigV1, OnChainConsensusConfig, OnChainExecutionConfig, ValidatorTxnConfig +}; +use aptos_testcases::two_traffics_test::TwoTrafficsTest; +use std::{num::NonZeroUsize, sync::Arc, time::Duration}; + +pub fn get_dag_test( + test_name: &str, + duration: Duration, + test_cmd: &TestCommand, +) -> Option { + get_dag_on_realistic_env_test(test_name, duration, test_cmd) +} + +/// Attempts to match the test name to a dag-realistic-env test +fn get_dag_on_realistic_env_test( + test_name: &str, + duration: Duration, + test_cmd: &TestCommand, +) -> Option { + let test = match test_name { + "dag_realistic_env_max_load" => dag_realistic_env_max_load_test(duration, test_cmd, 7, 5), + _ => return None, // The test name does not match a dag realistic-env test + }; + Some(test) +} + +fn dag_realistic_env_max_load_test( + duration: Duration, + test_cmd: &TestCommand, + num_validators: usize, + num_fullnodes: usize, +) -> ForgeConfig { + // Check if HAProxy is enabled + let ha_proxy = if let TestCommand::K8sSwarm(k8s) = test_cmd { + k8s.enable_haproxy + } else { + false + }; + + // Determine if this is a long running test + let duration_secs = duration.as_secs(); + let long_running = duration_secs >= 2400; + + // Create the test + ForgeConfig::default() + .with_initial_validator_count(NonZeroUsize::new(num_validators).unwrap()) + .with_initial_fullnode_count(num_fullnodes) + .add_network_test(wrap_with_realistic_env(TwoTrafficsTest { + inner_traffic: EmitJobRequest::default() + .mode(EmitJobMode::MaxLoad { + mempool_backlog: 40000, + }) + .init_gas_price_multiplier(20), + inner_success_criteria: SuccessCriteria::new( + if ha_proxy { + 4600 + } else if long_running { + // This is for forge stable + 7000 + } else { + // During land time we want to be less strict, otherwise we flaky fail + 6000 + }, + ), + })) + .with_genesis_helm_config_fn(Arc::new(move |helm_values| { + let onchain_consensus_config = OnChainConsensusConfig::V3 { + alg: ConsensusAlgorithmConfig::DAG(DagConsensusConfigV1::default()), + vtxn: ValidatorTxnConfig::default_for_genesis(), + }; + + // Have single epoch change in land blocking, and a few on long-running + helm_values["chain"]["epoch_duration_secs"] = + (if long_running { 600 } else { 300 }).into(); + helm_values["chain"]["on_chain_consensus_config"] = + serde_yaml::to_value(onchain_consensus_config).expect("must serialize"); + helm_values["chain"]["on_chain_execution_config"] = + serde_yaml::to_value(OnChainExecutionConfig::default_for_genesis()) + .expect("must serialize"); + })) + // First start higher gas-fee traffic, to not cause issues with TxnEmitter setup - account creation + .with_emit_job( + EmitJobRequest::default() + .mode(EmitJobMode::ConstTps { tps: 100 }) + .gas_price(5 * aptos_global_constants::GAS_UNIT_PRICE) + .latency_polling_interval(Duration::from_millis(100)), + ) + .with_success_criteria( + SuccessCriteria::new(95) + .add_no_restarts() + .add_wait_for_catchup_s( + // Give at least 60s for catchup, give 10% of the run for longer durations. + (duration.as_secs() / 10).max(60), + ) + .add_latency_threshold(3.4, LatencyType::P50) + .add_latency_threshold(4.5, LatencyType::P90) + .add_chain_progress(StateProgressThreshold { + max_no_progress_secs: 15.0, + max_round_gap: 4, + }), + ) +} diff --git a/testsuite/forge-cli/src/suites/mod.rs b/testsuite/forge-cli/src/suites/mod.rs new file mode 100644 index 00000000000000..ce1ed5778fcfc4 --- /dev/null +++ b/testsuite/forge-cli/src/suites/mod.rs @@ -0,0 +1 @@ +pub mod dag; \ No newline at end of file