A comprehensive testing and benchmarking framework for Solana programs using LiteSVM. Provides ergonomic, type-safe assertions for transaction results, logs, and all levels of Solana errors, plus systematic compute unit (CU) analysis for performance optimization.
β οΈ Development Status: This library is currently in active development. The API may change before the first stable release.
- π― Complete Error Testing: Transaction, instruction, and system program errors with type safety
- π Log Assertions: Detailed log content verification with helpful error messages
- π§ Build System Integration: Automatic program compilation for Anchor and Pinocchio
- β‘ Dual API Styles: Direct function calls or fluent method syntax
- πͺ Precision Control: "Anywhere" matching vs surgical instruction-index targeting
- π‘οΈ Type Safety: Work with
SystemError
enums instead of raw error codes - π Educational Examples: Learn API progression from verbose to elegant
- β‘ Systematic CU Analysis: Measure compute unit usage with statistical accuracy
- π¬ Dual Paradigms: Pure instruction benchmarking vs complete transaction workflows
- π Percentile-Based Estimates: Min, conservative, balanced, safe, very high, and max CU usage
- π― Production-Ready: Generate CU estimates for real-world fee planning
- π Rich Context: Execution logs, program details, and SVM environment state
- π Reproducible: Consistent results across environments and runs
- Testing: Anchor, Pinocchio, with more coming
- Benchmarking: Universal framework for any Solana program
Add to your Cargo.toml
:
[dev-dependencies]
litesvm-testing = { git = "https://github.com/levicook/litesvm-testing" }
litesvm = "0.6.1"
Once published to crates.io, you'll be able to use:
[dev-dependencies]
litesvm-testing = "0.1.0" # When available
litesvm = "0.6.1"
use litesvm_testing::prelude::*;
#[test]
fn test_my_program() {
let (mut svm, fee_payer) = setup_svm_and_fee_payer();
// ... load your program and create transaction ...
let result = svm.send_transaction(tx);
// Test successful execution
result.demand_logs_contain("Hello from my program!");
// Or test error conditions with type safety
result.demand_system_error(SystemError::ResultWithNegativeLamports);
}
use litesvm_testing::prelude::*;
#[test]
fn test_my_program_fluently() {
let (mut svm, fee_payer) = setup_svm_and_fee_payer();
// ... load your program and create transaction ...
let result = svm.send_transaction(tx);
// Call assertions as methods on the result
result.demand_logs_contain("Hello from my program!");
result.demand_instruction_error_at_index(1, InstructionError::Custom(42));
}
Test errors at every level of the Solana execution model:
Validation errors before execution:
result.demand_transaction_error(TransactionError::AlreadyProcessed);
Errors during instruction execution:
// "Anywhere" - don't care which instruction failed
result.demand_instruction_error(InstructionError::Custom(1));
// "Surgical" - specific instruction must fail
result.demand_instruction_error_at_index(1, InstructionError::Custom(1));
Type-safe system program errors:
// "Anywhere" - system error occurred somewhere
result.demand_system_error(SystemError::ResultWithNegativeLamports);
// "Surgical" - specific instruction produced system error
result.demand_system_error_at_index(1, SystemError::AccountAlreadyInUse);
Complete build system integration with IDL support:
[build-dependencies]
litesvm-testing = { git = "...", features = ["anchor"] }
// build.rs
use litesvm_testing::anchor_testing::build_anchor_program;
fn main() {
build_anchor_program("../my-anchor-program");
}
Lightweight compilation with minimal boilerplate:
[build-dependencies]
litesvm-testing = { git = "...", features = ["pinocchio"] }
// build.rs
use litesvm_testing::pinocchio_testing::build_pinocchio_program;
fn main() {
build_pinocchio_program("../my-pinocchio-program");
}
// Search all logs for content
result.demand_logs_contain("Hello from my program!");
// Check specific log entry by index
result.demand_logs_contain_at_index("Specific message", 2);
// Test transaction-level failures
result.demand_transaction_error(TransactionError::InsufficientFundsForFee);
result.demand_transaction_error(TransactionError::AccountNotFound);
// Test any instruction failure
result.demand_instruction_error(InstructionError::Custom(1));
result.demand_instruction_error(InstructionError::InvalidAccountData);
// Test specific instruction failure
result.demand_instruction_error_at_index(1, InstructionError::Custom(42));
// Test system program errors anywhere
result.demand_system_error(SystemError::ResultWithNegativeLamports);
result.demand_system_error(SystemError::AccountAlreadyInUse);
// Test system errors at specific instruction
result.demand_system_error_at_index(0, SystemError::InsufficientFunds);
// Quick SVM setup with funded fee payer
let (mut svm, fee_payer) = setup_svm_and_fee_payer();
Direct Functions (traditional):
demand_logs_contain("Hello!", result);
demand_system_error(SystemError::InsufficientFunds, result);
Fluent Methods (alternative syntax):
result.demand_logs_contain("Hello!");
result.demand_system_error(SystemError::InsufficientFunds);
Both styles provide identical functionality - choose what feels right for your team!
Note: Chainable fluent methods (
DemandChaining
) are planned for a future release, which will enableresult.demand_x().demand_y().accept()
style chaining.
This repository includes comprehensive, documented examples:
- Program:
examples/anchor/simple-anchor-program/
- Tests:
examples/anchor/simple-anchor-tests/
- Features: IDL integration, automatic compilation, complete build documentation
- Program:
examples/pinocchio/simple-pinocchio-program/
- Tests:
examples/pinocchio/simple-pinocchio-tests/
- Features: Minimal boilerplate, lightweight setup, direct BPF compilation
- API Progression:
tests/test_system_error_insufficient_funds.rs
- Features: Good β Better β Best β Best+ progression, demonstrates all API styles
- SOL Transfer:
benches/cu_bench_sol_transfer_ix.rs
- Pure system program instruction (150 CU) - SPL Token Transfer:
benches/cu_bench_spl_transfer_ix.rs
- Complex multi-account instruction
- Token Setup Workflow:
benches/cu_bench_token_setup_tx.rs
- Complete 5-instruction workflow (28K-38K CU)
- Complete Guide:
BENCHMARKING.md
- Comprehensive benchmarking documentation
# Clone the repository
git clone https://github.com/levicook/litesvm-testing
cd litesvm-testing
# Run all tests with detailed output
cargo test --workspace --no-fail-fast -- --show-output
# Run specific framework tests
cargo test -p simple-anchor-tests -- --show-output
cargo test -p simple-pinocchio-tests -- --show-output
# Run educational test suite
cargo test -p litesvm-testing test_system_error -- --show-output
# Run CU benchmarks with progress logging
cd crates/litesvm-testing
RUST_LOG=info cargo bench --bench cu_bench_sol_transfer_ix --features cu_bench
RUST_LOG=info cargo bench --bench cu_bench_token_setup_tx --features cu_bench
- Rust (latest stable)
- Solana CLI tools for
cargo build-sbf
command
Install all Solana development dependencies with one command:
curl --proto '=https' --tlsv1.2 -sSfL https://solana-install.solana.workers.dev | bash
This installs Rust, Solana CLI, Anchor CLI, Node.js, and Yarn all at once.
If the quick install doesn't work, install the Solana CLI individually:
sh -c "$(curl -sSfL https://release.anza.xyz/stable/install)"
Note: The Solana CLI is now maintained by Anza (formerly Solana Labs) and uses the Agave validator client.
Check that everything is installed correctly:
# Check Solana CLI
solana --version
# Expected: solana-cli 2.2.12 (src:0315eb6a; feat:1522022101, client:Agave)
# Check Rust
rustc --version
# Expected: rustc 1.86.0 (05f9846f8 2025-03-31)
litesvm-testing/
βββ crates/
β βββ litesvm-testing/ # Core library with comprehensive docs
β βββ src/
β β βββ lib.rs # Main API and documentation
β β βββ anchor_testing/ # Anchor build utilities
β β βββ pinocchio_testing/ # Pinocchio build utilities
β βββ tests/ # Educational test examples
βββ examples/
β βββ anchor/ # Complete Anchor integration
β β βββ simple-anchor-program/
β β βββ simple-anchor-tests/
β βββ pinocchio/ # Complete Pinocchio integration
β βββ simple-pinocchio-program/
β βββ simple-pinocchio-tests/
βββ README.md # This file
- Core log assertion utilities
- Complete error testing framework (transaction, instruction, system)
- Type-safe system error handling
- Anchor and Pinocchio build support with comprehensive documentation
- Working examples for both frameworks with educational progression
- Dual API styles (direct functions + fluent method syntax)
- Precision control ("anywhere" vs "surgical" assertions)
- CU benchmarking framework with instruction and transaction paradigms
- Statistical CU analysis with percentile-based estimates
- Rich benchmarking context (execution logs, program details, SVM state)
- Steel framework support
- Additional testing utilities (account state verification, etc.)
- First stable release (v0.1.0) to crates.io
- Integration with popular Solana testing patterns
This library is designed not just as a tool, but as a learning resource:
- Progressive examples: See how testing approaches evolve from verbose to elegant
- Framework comparisons: Understand trade-offs between Anchor and Pinocchio
- Complete documentation: Every function includes usage examples and context
- Real error scenarios: Test actual system program failures, not synthetic examples
This project is dual licensed under GPL-3.0-or-later and CC BY-SA 4.0. See LICENSE for details.