Документація SolanaLiteSVMRustТестування вашої програми

Розгортання програм

Початок роботи

let mut svm = LiteSVM::new();

Це створює базовий тестовий екземпляр litesvm, який включає всі увімкнені функції середовища виконання, стандартні sysvar, прекомпіляції, програми spl, sigverify та всі вбудовані програми, як-от System Program.

Щоб взаємодіяти з будь-якою іншою програмою у своїх тестах, необхідно розгорнути цю програму у тестовому середовищі.

  1. Зберіть і розгорніть програму, яку хочете протестувати

  2. Знайдіть усі програми, до яких наведена вище програма здійснює CPI-виклики, і розгорніть їх

Приклад: Якщо ваша програма використовує дані про ціни від Pyth, вам потрібно розгорнути програму Pyth у своєму тестовому екземплярі.

Базове розгортання програм

Метод 1: Розгортання з байтів

Розгортайте програми безпосередньо з байтових масивів для найшвидшого виконання тестів:

use litesvm::LiteSVM;
use solana_sdk::signature::{read_keypair_file, Signer};
let mut svm = LiteSVM::new();
// Read the program's keypair to get correct ID
let program_keypair = read_keypair_file("target/deploy/my_program-keypair.json")
.expect("Program keypair file not found");
let program_id = program_keypair.pubkey();
// Include bytes at compile time
let program_bytes = include_bytes!("../target/deploy/my_program.so");
// Deploy from bytes
svm.add_program(program_id, program_bytes)
.expect("Failed to deploy program");
// Verify deployment
assert!(svm.get_account(&program_id).is_some(), "Program account not created");
assert!(svm.get_account(&program_id).unwrap().executable, "Program not executable");

include_bytes! вбудовує двійковий файл безпосередньо у виконуваний файл тесту під час компіляції, що усуває операції введення/виведення під час виконання тестів.

Переваги

  • Швидше під час виконання (без зчитування з диска)
  • Самодостатній виконуваний файл тесту
  • Працює навіть якщо файл .so видалено після компіляції

Недоліки

  • Більший розмір виконуваного файлу тесту
  • Необхідно перекомпілювати тести при зміні файлу .so

Метод 2: Розгортання з файлу (.so)

Завантажуйте програми з файлової системи, коли вони часто змінюються:

use litesvm::LiteSVM;
use solana_sdk::signature::{read_keypair_file, Signer};
let mut svm = LiteSVM::new();
// Read keypair for correct program ID
let program_keypair = read_keypair_file("target/deploy/program-keypair.json").unwrap();
let program_id = program_keypair.pubkey();
// Deploy from file
svm.add_program_from_file(program_id, "target/deploy/program.so")
.expect("Failed to deploy program from file");
// Always verify
assert!(svm.get_account(&program_id).unwrap().executable);

Переваги

  • Менший тестовий бінарний файл
  • Можна підхоплювати зміни .so без перекомпіляції тестів
  • Більша гнучкість для CI/CD-конвеєрів

Недоліки

  • Повільніше (дисковий ввід/вивід під час виконання)
  • Файл .so має існувати на момент виконання тесту
  • Шлях до файлу має бути правильним відносно каталогу виконання тестів

Завантаження програм із Mainnet/Devnet

Якщо вам потрібна програма, вихідного коду якої у вас немає, скористайтесь Solana CLI, щоб вивантажити програми з живих кластерів і використовувати їх у тестах:

# Dump a program from mainnet
solana program dump gSbePebfvPy7tRqimPoVecS2UsBvYv46ynrzWocc92s pyth.so --url mainnet-beta
# Dump from devnet
solana program dump YourProgramID program.so --url devnet

Потім завантажте її у своїх тестах:

svm.add_program_from_file(
pubkey!("gSbePebfvPy7tRqimPoVecS2UsBvYv46ynrzWocc92s"),
"pyth.so"
).unwrap();

Найкращі практики

1. Виберіть правильний метод розгортання

  • Використовуйте add_program(), якщо:

    • Програми вбудовані у ваш тестовий бінарний файл під час компіляції
    • Вам потрібне швидше виконання тестів (без ввід/виводу під час виконання)
    • Тести є самодостатніми
  • Використовуйте add_program_from_file(), коли:

    • Програми зібрані окремо (тобто завантажуються з devnet)
    • Програми часто змінюються під час розробки (можна повторно запускати тести без перекомпіляції)
    • У вас є середовища CI/CD, де файли .so є артефактами

Розуміння keypair програми

Коли ви збираєте програму Solana:

  1. Anchor створює target/deploy/program-keypair.json
  2. Native збірки створюють файл keypair поруч із файлом .so
  3. Адреса програми в мережі — це pubkey цього keypair, яка також відома як ідентифікатор програми.
  4. Для PDA find_program_address() потребує ідентифікатор програми як seed
  5. Для CPI ідентифікатор програми використовується для виклику інших програм

Поширені проблеми та рішення

Приховані збої розгортання

Проблема: Програма, здається, розгорнута, але транзакції завершуються помилкою "InvalidProgramForExecution".

Причина: Ідентифікатор програми не відповідає keypair.

Рішення:

// Always use the keypair-derived ID
let keypair = read_keypair_file("target/deploy/program-keypair.json").unwrap();
let program_id = keypair.pubkey();
svm.add_program(program_id, &program_bytes).unwrap();
// Verify with detailed checks
let account = svm.get_account(&program_id)
.expect("Program account doesn't exist");
assert!(account.executable, "Program not executable");
assert_eq!(account.owner, solana_sdk::bpf_loader::id(), "Wrong owner");
assert!(!account.data.is_empty(), "Program data is empty");
println!("✅ Program verified at {}", program_id);

Помилка «Програму не знайдено»

Помилка: TransactionError::InvalidProgramForExecution

Поширені причини:

  1. Програму не розгорнуто
  2. У інструкції використовується неправильний ідентифікатор програми
  3. Невідповідність ідентифікатора програми з keypair

Кроки для налагодження:

// Step 1: Check if program exists
if let Some(account) = svm.get_account(&program_id) {
println!("Program exists");
println!(" Executable: {}", account.executable);
println!(" Owner: {}", account.owner);
println!(" Data length: {}", account.data.len());
} else {
println!("Program does not exist at {}", program_id);
}
// Step 2: Verify the ID matches keypair
let expected_keypair = read_keypair_file("target/deploy/program-keypair.json").unwrap();
let expected_id = expected_keypair.pubkey();
if program_id != expected_id {
println!(" ID mismatch!");
println!(" Used: {}", program_id);
println!(" Expected: {}", expected_id);
}
// Step 3: Check instruction program ID
println!("Instruction program_id: {}", instruction.program_id);
assert_eq!(instruction.program_id, program_id, "Instruction uses wrong program ID");

CPI до нерозгорнутих програм

Проблема: Ваша програма здійснює виклик CPI до програми, яка не розгорнута.

Рішення: Розгорніть усі залежні програми:

// Find all dependency programs and make sure they are deployed
svm.add_program_from_file(
pubkey!("gSbePebfvPy7tRqimPoVecS2UsBvYv46ynrzWocc92s"),
"pyth.so"
).unwrap();

Якщо вам потрібно завантажити програму з кластера, перегляньте цей розділ.

Недостатньо lamport для розгортання

Примітка: LiteSVM автоматично обробляє баланс, звільнений від орендної плати, для програм.

// No need to manually fund - LiteSVM handles this
svm.add_program(program_id, &program_bytes).unwrap();
// But you can check the rent if needed
let program_len = program_bytes.len();
let required_lamports = svm.minimum_balance_for_rent_exemption(program_len);
println!("Program requires {} lamports for rent exemption", required_lamports);

Контрольний список перевірки розгортання

Зчитайте keypair програми

let keypair = read_keypair_file("target/deploy/program-keypair.json").unwrap();
let program_id = keypair.pubkey();

Розгорніть з відповідним ID

svm.add_program(program_id, &program_bytes).unwrap();

Перевірте розгортання

assert!(svm.get_account(&program_id).unwrap().executable);

Розгорніть усі програми, які ваша програма викликає через CPI, до тестового екземпляра litesvm

Наступні кроки

У наступному розділі ми дізнаємося, як виконувати інструкції програми та обробляти складні патерни транзакцій.

Is this page helpful?