2025-12-01 12:48:39 +01:00
|
|
|
# Builder API Quick Reference
|
|
|
|
|
|
|
|
|
|
Quick reference for the scenario builder DSL. All methods are chainable.
|
|
|
|
|
|
|
|
|
|
## Imports
|
|
|
|
|
|
|
|
|
|
```rust
|
2025-12-16 06:55:44 +01:00
|
|
|
use std::time::Duration;
|
|
|
|
|
|
2025-12-01 12:48:39 +01:00
|
|
|
use testing_framework_core::scenario::{Deployer, ScenarioBuilder};
|
|
|
|
|
use testing_framework_runner_compose::ComposeDeployer;
|
|
|
|
|
use testing_framework_runner_k8s::K8sDeployer;
|
2025-12-16 06:55:44 +01:00
|
|
|
use testing_framework_runner_local::LocalDeployer;
|
|
|
|
|
use testing_framework_workflows::{ChaosBuilderExt, ScenarioBuilderExt};
|
2025-12-01 12:48:39 +01:00
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## Topology
|
|
|
|
|
|
|
|
|
|
```rust
|
2025-12-16 06:55:44 +01:00
|
|
|
use testing_framework_core::scenario::{Builder, ScenarioBuilder};
|
|
|
|
|
|
|
|
|
|
pub fn topology() -> Builder<()> {
|
|
|
|
|
ScenarioBuilder::topology_with(|t| {
|
|
|
|
|
t.network_star() // Star topology (all connect to seed node)
|
|
|
|
|
.validators(3) // Number of validator nodes
|
|
|
|
|
.executors(2) // Number of executor nodes
|
|
|
|
|
})
|
|
|
|
|
}
|
2025-12-01 12:48:39 +01:00
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## Wallets
|
|
|
|
|
|
|
|
|
|
```rust
|
2025-12-16 06:55:44 +01:00
|
|
|
use testing_framework_core::scenario::ScenarioBuilder;
|
|
|
|
|
use testing_framework_workflows::ScenarioBuilderExt;
|
|
|
|
|
|
|
|
|
|
pub fn wallets_plan() -> testing_framework_core::scenario::Scenario<()> {
|
|
|
|
|
ScenarioBuilder::topology_with(|t| t.network_star().validators(1).executors(0))
|
|
|
|
|
.wallets(50) // Seed 50 funded wallet accounts
|
|
|
|
|
.build()
|
|
|
|
|
}
|
2025-12-01 12:48:39 +01:00
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## Transaction Workload
|
|
|
|
|
|
|
|
|
|
```rust
|
2025-12-16 06:55:44 +01:00
|
|
|
use testing_framework_core::scenario::ScenarioBuilder;
|
|
|
|
|
use testing_framework_workflows::ScenarioBuilderExt;
|
|
|
|
|
|
|
|
|
|
pub fn transactions_plan() -> testing_framework_core::scenario::Scenario<()> {
|
|
|
|
|
ScenarioBuilder::topology_with(|t| t.network_star().validators(1).executors(0))
|
|
|
|
|
.wallets(50)
|
|
|
|
|
.transactions_with(|txs| {
|
|
|
|
|
txs.rate(5) // 5 transactions per block
|
|
|
|
|
.users(20) // Use 20 of the seeded wallets
|
|
|
|
|
}) // Finish transaction workload config
|
|
|
|
|
.build()
|
|
|
|
|
}
|
2025-12-01 12:48:39 +01:00
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## DA Workload
|
|
|
|
|
|
|
|
|
|
```rust
|
2025-12-16 06:55:44 +01:00
|
|
|
use testing_framework_core::scenario::ScenarioBuilder;
|
|
|
|
|
use testing_framework_workflows::ScenarioBuilderExt;
|
|
|
|
|
|
|
|
|
|
pub fn da_plan() -> testing_framework_core::scenario::Scenario<()> {
|
|
|
|
|
ScenarioBuilder::topology_with(|t| t.network_star().validators(1).executors(1))
|
|
|
|
|
.wallets(50)
|
|
|
|
|
.da_with(|da| {
|
|
|
|
|
da.channel_rate(1) // number of DA channels to run
|
|
|
|
|
.blob_rate(2) // target 2 blobs per block (headroom applied)
|
|
|
|
|
.headroom_percent(20) // optional headroom when sizing channels
|
|
|
|
|
}) // Finish DA workload config
|
|
|
|
|
.build()
|
|
|
|
|
}
|
2025-12-01 12:48:39 +01:00
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## Chaos Workload (Requires `enable_node_control()`)
|
|
|
|
|
|
|
|
|
|
```rust
|
2025-12-16 06:55:44 +01:00
|
|
|
use std::time::Duration;
|
|
|
|
|
|
|
|
|
|
use testing_framework_core::scenario::{NodeControlCapability, ScenarioBuilder};
|
|
|
|
|
use testing_framework_workflows::{ChaosBuilderExt, ScenarioBuilderExt};
|
|
|
|
|
|
|
|
|
|
pub fn chaos_plan() -> testing_framework_core::scenario::Scenario<NodeControlCapability> {
|
|
|
|
|
ScenarioBuilder::topology_with(|t| t.network_star().validators(3).executors(2))
|
|
|
|
|
.enable_node_control() // Enable node control capability
|
|
|
|
|
.chaos_with(|c| {
|
|
|
|
|
c.restart() // Random restart chaos
|
|
|
|
|
.min_delay(Duration::from_secs(30)) // Min time between restarts
|
|
|
|
|
.max_delay(Duration::from_secs(60)) // Max time between restarts
|
|
|
|
|
.target_cooldown(Duration::from_secs(45)) // Cooldown after restart
|
|
|
|
|
.apply() // Required for chaos configuration
|
|
|
|
|
})
|
|
|
|
|
.build()
|
|
|
|
|
}
|
2025-12-01 12:48:39 +01:00
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## Expectations
|
|
|
|
|
|
|
|
|
|
```rust
|
2025-12-16 06:55:44 +01:00
|
|
|
use testing_framework_core::scenario::ScenarioBuilder;
|
|
|
|
|
use testing_framework_workflows::ScenarioBuilderExt;
|
|
|
|
|
|
|
|
|
|
pub fn expectations_plan() -> testing_framework_core::scenario::Scenario<()> {
|
|
|
|
|
ScenarioBuilder::topology_with(|t| t.network_star().validators(1).executors(0))
|
|
|
|
|
.expect_consensus_liveness() // Assert blocks are produced continuously
|
|
|
|
|
.build()
|
|
|
|
|
}
|
2025-12-01 12:48:39 +01:00
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## Run Duration
|
|
|
|
|
|
|
|
|
|
```rust
|
2025-12-16 06:55:44 +01:00
|
|
|
use std::time::Duration;
|
|
|
|
|
|
|
|
|
|
use testing_framework_core::scenario::ScenarioBuilder;
|
|
|
|
|
use testing_framework_workflows::ScenarioBuilderExt;
|
|
|
|
|
|
|
|
|
|
pub fn run_duration_plan() -> testing_framework_core::scenario::Scenario<()> {
|
|
|
|
|
ScenarioBuilder::topology_with(|t| t.network_star().validators(1).executors(0))
|
|
|
|
|
.with_run_duration(Duration::from_secs(120)) // Run for 120 seconds
|
|
|
|
|
.build()
|
|
|
|
|
}
|
2025-12-01 12:48:39 +01:00
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## Build
|
|
|
|
|
|
|
|
|
|
```rust
|
2025-12-16 06:55:44 +01:00
|
|
|
use testing_framework_core::scenario::ScenarioBuilder;
|
|
|
|
|
use testing_framework_workflows::ScenarioBuilderExt;
|
|
|
|
|
|
|
|
|
|
pub fn build_plan() -> testing_framework_core::scenario::Scenario<()> {
|
|
|
|
|
ScenarioBuilder::topology_with(|t| t.network_star().validators(1).executors(0)).build() // Construct the final Scenario
|
|
|
|
|
}
|
2025-12-01 12:48:39 +01:00
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## Deployers
|
|
|
|
|
|
|
|
|
|
```rust
|
2025-12-16 06:55:44 +01:00
|
|
|
use testing_framework_runner_compose::ComposeDeployer;
|
|
|
|
|
use testing_framework_runner_k8s::K8sDeployer;
|
|
|
|
|
use testing_framework_runner_local::LocalDeployer;
|
|
|
|
|
|
|
|
|
|
pub fn deployers() {
|
|
|
|
|
// Local processes
|
|
|
|
|
let _deployer = LocalDeployer::default();
|
2025-12-01 12:48:39 +01:00
|
|
|
|
2025-12-16 06:55:44 +01:00
|
|
|
// Docker Compose
|
|
|
|
|
let _deployer = ComposeDeployer::default();
|
2025-12-01 12:48:39 +01:00
|
|
|
|
2025-12-16 06:55:44 +01:00
|
|
|
// Kubernetes
|
|
|
|
|
let _deployer = K8sDeployer::default();
|
|
|
|
|
}
|
2025-12-01 12:48:39 +01:00
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## Execution
|
|
|
|
|
|
|
|
|
|
```rust
|
2025-12-16 06:55:44 +01:00
|
|
|
use anyhow::Result;
|
|
|
|
|
use testing_framework_core::scenario::{Deployer, ScenarioBuilder};
|
|
|
|
|
use testing_framework_runner_local::LocalDeployer;
|
|
|
|
|
use testing_framework_workflows::ScenarioBuilderExt;
|
|
|
|
|
|
|
|
|
|
pub async fn execution() -> Result<()> {
|
|
|
|
|
let mut plan = ScenarioBuilder::topology_with(|t| t.network_star().validators(1).executors(0))
|
|
|
|
|
.expect_consensus_liveness()
|
|
|
|
|
.build();
|
|
|
|
|
|
|
|
|
|
let deployer = LocalDeployer::default();
|
|
|
|
|
let runner = deployer.deploy(&plan).await?;
|
|
|
|
|
let _handle = runner.run(&mut plan).await?;
|
|
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
|
}
|
2025-12-01 12:48:39 +01:00
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## Complete Example
|
|
|
|
|
|
|
|
|
|
```rust
|
2025-12-16 06:55:44 +01:00
|
|
|
use std::time::Duration;
|
|
|
|
|
|
|
|
|
|
use anyhow::Result;
|
2025-12-01 12:48:39 +01:00
|
|
|
use testing_framework_core::scenario::{Deployer, ScenarioBuilder};
|
|
|
|
|
use testing_framework_runner_local::LocalDeployer;
|
|
|
|
|
use testing_framework_workflows::ScenarioBuilderExt;
|
|
|
|
|
|
2025-12-16 06:55:44 +01:00
|
|
|
pub async fn run_test() -> Result<()> {
|
|
|
|
|
let mut plan = ScenarioBuilder::topology_with(|t| t.network_star().validators(3).executors(2))
|
2025-12-01 12:48:39 +01:00
|
|
|
.wallets(50)
|
2025-12-03 06:20:59 +01:00
|
|
|
.transactions_with(|txs| {
|
2025-12-16 06:55:44 +01:00
|
|
|
txs.rate(5) // 5 transactions per block
|
2025-12-03 06:20:59 +01:00
|
|
|
.users(20)
|
|
|
|
|
})
|
|
|
|
|
.da_with(|da| {
|
2025-12-16 06:55:44 +01:00
|
|
|
da.channel_rate(1) // number of DA channels
|
|
|
|
|
.blob_rate(2) // target 2 blobs per block
|
|
|
|
|
.headroom_percent(20) // optional channel headroom
|
2025-12-03 06:20:59 +01:00
|
|
|
})
|
2025-12-01 12:48:39 +01:00
|
|
|
.expect_consensus_liveness()
|
|
|
|
|
.with_run_duration(Duration::from_secs(90))
|
|
|
|
|
.build();
|
|
|
|
|
|
|
|
|
|
let deployer = LocalDeployer::default();
|
|
|
|
|
let runner = deployer.deploy(&plan).await?;
|
|
|
|
|
let _handle = runner.run(&mut plan).await?;
|
2025-12-16 06:55:44 +01:00
|
|
|
|
2025-12-01 12:48:39 +01:00
|
|
|
Ok(())
|
|
|
|
|
}
|
|
|
|
|
```
|