2025-12-01 12:48:39 +01:00
|
|
|
# Examples
|
|
|
|
|
|
|
|
|
|
Concrete scenario shapes that illustrate how to combine topologies, workloads,
|
|
|
|
|
and expectations.
|
|
|
|
|
|
2025-12-18 17:26:02 +01:00
|
|
|
**View Complete Source Code:**
|
2025-12-18 18:36:38 +01:00
|
|
|
- [local_runner.rs](https://github.com/logos-blockchain/logos-blockchain-testing/blob/master/examples/src/bin/local_runner.rs) — Host processes (local)
|
|
|
|
|
- [compose_runner.rs](https://github.com/logos-blockchain/logos-blockchain-testing/blob/master/examples/src/bin/compose_runner.rs) — Docker Compose
|
|
|
|
|
- [k8s_runner.rs](https://github.com/logos-blockchain/logos-blockchain-testing/blob/master/examples/src/bin/k8s_runner.rs) — Kubernetes
|
2025-12-18 17:26:02 +01:00
|
|
|
|
2025-12-01 12:48:39 +01:00
|
|
|
**Runnable examples:** The repo includes complete binaries in `examples/src/bin/`:
|
2025-12-09 09:43:49 +01:00
|
|
|
- `local_runner.rs` — Host processes (local)
|
|
|
|
|
- `compose_runner.rs` — Docker Compose (requires image built)
|
2025-12-01 12:48:39 +01:00
|
|
|
- `k8s_runner.rs` — Kubernetes (requires cluster access and image loaded)
|
|
|
|
|
|
2025-12-18 17:26:02 +01:00
|
|
|
**Recommended:** Use `scripts/run/run-examples.sh -t <duration> -v <validators> -e <executors> <mode>` where mode is `host`, `compose`, or `k8s`.
|
2025-12-09 09:43:49 +01:00
|
|
|
|
|
|
|
|
**Alternative:** Direct cargo run: `POL_PROOF_DEV_MODE=true cargo run -p runner-examples --bin <name>`
|
2025-12-01 12:48:39 +01:00
|
|
|
|
|
|
|
|
**All runners require `POL_PROOF_DEV_MODE=true`** to avoid expensive proof generation.
|
|
|
|
|
|
|
|
|
|
**Code patterns** below show how to build scenarios. Wrap these in `#[tokio::test]` functions for integration tests, or `#[tokio::main]` for binaries.
|
|
|
|
|
|
|
|
|
|
## Simple consensus liveness
|
|
|
|
|
|
|
|
|
|
Minimal test that validates basic block production:
|
|
|
|
|
|
2025-12-20 09:16:23 +01:00
|
|
|
```rust,ignore
|
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 simple_consensus() -> Result<()> {
|
|
|
|
|
let mut plan = ScenarioBuilder::topology_with(|t| t.network_star().validators(3).executors(0))
|
2025-12-01 12:48:39 +01:00
|
|
|
.expect_consensus_liveness()
|
|
|
|
|
.with_run_duration(Duration::from_secs(30))
|
|
|
|
|
.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(())
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**When to use**: smoke tests for consensus on minimal hardware.
|
|
|
|
|
|
|
|
|
|
## Transaction workload
|
|
|
|
|
|
|
|
|
|
Test consensus under transaction load:
|
|
|
|
|
|
2025-12-20 09:16:23 +01:00
|
|
|
```rust,ignore
|
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 transaction_workload() -> Result<()> {
|
|
|
|
|
let mut plan = ScenarioBuilder::topology_with(|t| t.network_star().validators(2).executors(0))
|
2025-12-01 12:48:39 +01:00
|
|
|
.wallets(20)
|
2025-12-16 06:55:44 +01:00
|
|
|
.transactions_with(|txs| txs.rate(5).users(10))
|
2025-12-01 12:48:39 +01:00
|
|
|
.expect_consensus_liveness()
|
|
|
|
|
.with_run_duration(Duration::from_secs(60))
|
|
|
|
|
.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(())
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**When to use**: validate transaction submission and inclusion.
|
|
|
|
|
|
|
|
|
|
## DA + transaction workload
|
|
|
|
|
|
|
|
|
|
Combined test stressing both transaction and DA layers:
|
|
|
|
|
|
2025-12-20 09:16:23 +01:00
|
|
|
```rust,ignore
|
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 da_and_transactions() -> Result<()> {
|
|
|
|
|
let mut plan = ScenarioBuilder::topology_with(|t| t.network_star().validators(3).executors(2))
|
2025-12-01 12:48:39 +01:00
|
|
|
.wallets(30)
|
2025-12-16 06:55:44 +01:00
|
|
|
.transactions_with(|txs| txs.rate(5).users(15))
|
|
|
|
|
.da_with(|da| da.channel_rate(2).blob_rate(2))
|
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(())
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**When to use**: end-to-end coverage of transaction and DA layers.
|
|
|
|
|
|
|
|
|
|
## Chaos resilience
|
|
|
|
|
|
|
|
|
|
Test system resilience under node restarts:
|
|
|
|
|
|
2025-12-20 09:16:23 +01:00
|
|
|
```rust,ignore
|
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_compose::ComposeDeployer;
|
2025-12-16 06:55:44 +01:00
|
|
|
use testing_framework_workflows::{ChaosBuilderExt, ScenarioBuilderExt};
|
2025-12-01 12:48:39 +01:00
|
|
|
|
2025-12-16 06:55:44 +01:00
|
|
|
pub async fn chaos_resilience() -> Result<()> {
|
|
|
|
|
let mut plan = ScenarioBuilder::topology_with(|t| t.network_star().validators(4).executors(2))
|
2025-12-01 12:48:39 +01:00
|
|
|
.enable_node_control()
|
|
|
|
|
.wallets(20)
|
2025-12-16 06:55:44 +01:00
|
|
|
.transactions_with(|txs| txs.rate(3).users(10))
|
2025-12-06 10:17:06 +01:00
|
|
|
.chaos_with(|c| {
|
|
|
|
|
c.restart()
|
|
|
|
|
.min_delay(Duration::from_secs(20))
|
|
|
|
|
.max_delay(Duration::from_secs(40))
|
|
|
|
|
.target_cooldown(Duration::from_secs(30))
|
|
|
|
|
.apply()
|
|
|
|
|
})
|
2025-12-01 12:48:39 +01:00
|
|
|
.expect_consensus_liveness()
|
|
|
|
|
.with_run_duration(Duration::from_secs(120))
|
|
|
|
|
.build();
|
|
|
|
|
|
|
|
|
|
let deployer = ComposeDeployer::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(())
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
**When to use**: resilience validation and operational readiness drills.
|
|
|
|
|
|
|
|
|
|
**Note**: Chaos tests require `ComposeDeployer` or another runner with node control support.
|