# Light Program Test
A fast local test environment for Solana programs using compressed accounts and tokens.
For Rust and Anchor program development, see [`light-sdk`](https://docs.rs/light-sdk).
For Rust client, see [`light-client`](https://docs.rs/light-client).
For full program examples, see the [Program Examples](https://github.com/Lightprotocol/program-examples).
For detailed documentation, visit [zkcompression.com](https://www.zkcompression.com/).
# Features
- `v2` - Enables v2 batched Merkle trees.
## Testing Features
- Fast in-memory indexer and SVM via [LiteSVM](https://github.com/LiteSVM/LiteSVM)
- Supports custom programs
- Prover server via [Light CLI](https://www.npmjs.com/package/@lightprotocol/zk-compression-cli)
**Use `light-program-test` when:**
- You need fast test execution
- You write unit/integration tests for your program or client code
**Use `solana-test-validator` when:**
- You need RPC methods or external tools that are incompatible with LiteSVM
- Testing against real validator behavior
## Configuration Options
### `with_prover: bool`
- `true`: Starts a prover server in the background for generating validity proofs
- `false`: Runs without prover (faster for tests that don't need proofs, or repeated test runs to reduce startup time)
### `additional_programs: Option<Vec<(&str, Pubkey)>>`
- Specify custom programs to deploy alongside the default Light Protocol programs
- Format: `vec![("program_name", program_id)]`
- Programs are loaded from built artifacts
## Prerequisites
1. **ZK Compression CLI**: Required to start the prover server and download Light Protocol programs
```bash
npm i -g @lightprotocol/zk-compression-cli
```
- If programs are missing after CLI installation, run `light test-validator` once to download them
2. **Build programs**: Run `cargo test-sbf` to build program binaries and set the required
environment variables for locating program artifacts
## Prover Server
The prover server runs on port 3001 when enabled. To manually stop it:
```bash
# Find the process ID
lsof -i:3001
# Kill the process
kill <pid>
```
## Debugging
Set `RUST_BACKTRACE=1` to show detailed transaction information including accounts and parsed instructions:
```bash
RUST_BACKTRACE=1 cargo test-sbf -- --nocapture
```
## Examples
### V1 Trees
```rust
use light_program_test::{LightProgramTest, ProgramTestConfig};
use solana_sdk::signer::{keypair::Keypair, Signer};
#[tokio::test]
async fn test_v1_compressed_account() {
// Initialize with v1 trees
let config = ProgramTestConfig::default();
let mut rpc = LightProgramTest::new(config).await.unwrap();
let payer = Keypair::new();
// Get v1 tree info
let address_tree_info = rpc.get_address_tree_v1();
let state_tree_info = rpc.get_random_state_tree_info();
// Airdrop for testing
rpc.airdrop_lamports(&payer.pubkey(), 1_000_000_000).await.unwrap();
// Query compressed accounts using Indexer trait
let accounts = rpc.indexer().unwrap()
.get_compressed_accounts_by_owner(&payer.pubkey())
.await
.unwrap();
println!("Found {} compressed accounts", accounts.len());
}
```
### V2 Trees
```rust
use light_program_test::{LightProgramTest, ProgramTestConfig};
use solana_sdk::signer::{keypair::Keypair, Signer};
#[tokio::test]
async fn test_v2_compressed_account() {
// Initialize with v2 batched trees and custom program
let config = ProgramTestConfig::new_v2(
true, // with_prover
Some(vec![("my_program", my_program::ID)])
);
let mut rpc = LightProgramTest::new(config).await.unwrap();
let payer = Keypair::new();
// Get v2 tree pubkeys
let address_tree_info = rpc.get_address_tree_v2();
let state_tree_info = rpc.get_random_state_tree_info();
rpc.airdrop_lamports(&payer.pubkey(), 1_000_000_000).await.unwrap();
// Query using Indexer trait methods
let accounts = rpc.indexer().unwrap()
.get_compressed_accounts_by_owner(&payer.pubkey())
.await
.unwrap();
println!("Found {} compressed accounts with v2 trees", accounts.len());
}
```