---
title: Cross-Program Invocation
description: How to test programs calling other programs
---

## Complete Test

```rust title="tests/cpi_test.rs"
use litesvm::LiteSVM;
use solana_sdk::{
    instruction::{AccountMeta, Instruction},
    pubkey::Pubkey,
    signature::{Keypair, Signer},
    transaction::Transaction,
    system_program,
};

#[test]
fn test_cross_program_invocation() {
    let mut svm = LiteSVM::new();

    // Deploy both programs
    let caller_program = Pubkey::new_unique();
    let callee_program = Pubkey::new_unique();

    svm.add_program(
        caller_program,
        include_bytes!("../target/deploy/caller.so")
    ).unwrap();

    svm.add_program(
        callee_program,
        include_bytes!("../target/deploy/callee.so")
    ).unwrap();

    // Setup accounts
    let payer = Keypair::new();
    svm.airdrop(&payer.pubkey(), 10_000_000_000).unwrap();

    // Create instruction that will trigger CPI
    let instruction = Instruction {
        program_id: caller_program,
        accounts: vec![
            AccountMeta::new(payer.pubkey(), true),
            AccountMeta::new_readonly(callee_program, false),
            AccountMeta::new_readonly(system_program::id(), false),
        ],
        data: vec![1], // Instruction to trigger CPI
    };

    let tx = Transaction::new_signed_with_payer(
        &[instruction],
        Some(&payer.pubkey()),
        &[&payer],
        svm.latest_blockhash(),
    );

    let result = svm.send_transaction(tx).unwrap();

    // Verify both programs were invoked
    assert!(result.logs.iter().any(|log|
        log.contains(&format!("Program {} invoke", caller_program))
    ));
    assert!(result.logs.iter().any(|log|
        log.contains(&format!("Program {} invoke", callee_program))
    ));

    println!("CPI successful!");
    println!("Logs showing both programs:");
    for log in &result.logs {
        if log.contains("invoke") {
            println!("   {}", log);
        }
    }
}
```

## Key Points

1. **Multiple Programs**: Deploy all programs involved in the CPI chain
2. **Program IDs**: Pass the callee program ID as an account in the instruction
3. **System Program**: Often needed for CPI operations (transfers, account
   creation, etc.)
4. **Log Verification**: Check logs to verify all programs in the call chain
   executed

For more detailed deployment information, read
[this section](/docs/tools/litesvm/testing-your-program/deploy).

## Understanding CPI Logs

When a CPI occurs, you'll see logs like:

```
Program A invoke [1]
Program B invoke [2]
Program B success
Program A success
```

The numbers in brackets indicate the call depth.
