Solana-dokumentaatioOhjelmien kehittäminenTestausohjelmat

Mollusk

Mollusk on kevyt testaustyökalu Solana-ohjelmien testaamiseen. Se tarjoaa yksinkertaisen käyttöliittymän Solana-ohjelmien käskyjen testaamiseen minimoidussa Solana Virtual Machine (SVM) -ympäristössä. Kaikki testitilit on määriteltävä erikseen, mikä varmistaa deterministiset ja toistettavat testit.

Asennus

Lisää mollusk-svm riippuvuudeksi tiedostoon Cargo.toml:

Terminal
$
cargo add mollusk-svm --dev
Cargo.toml
[dev-dependencies]
mollusk-svm = "0.5"

Laskentayksiköiden käytön mittaamiseksi lisää mollusk-svm-bencher riippuvuudeksi tiedostoon Cargo.toml:

Terminal
$
cargo add mollusk-svm-bencher --dev
Cargo.toml
[dev-dependencies]
mollusk-svm-bencher = "0.5"

Käyttääksesi Token Program -ohjelmaa, token2022-ohjelmaa (Token Extensions) ja Associated Token Program -ohjelmaa Molluskin kanssa testaamiseen, lisää mollusk-svm-programs-token riippuvuudeksi tiedostoon Cargo.toml:

Terminal
$
cargo add mollusk-svm-programs-token --dev
Cargo.toml
[dev-dependencies]
mollusk-svm-programs-token = "0.5"

Mollusk SVM

Seuraava esimerkki näyttää minimaalisen asetuksen perus-Solana-ohjelman testaamiseen Molluskin avulla.

Hello World -ohjelma

Tämä esimerkki havainnollistaa, miten testataan perus-Solana-ohjelmaa Molluskin avulla. Ohjelma yksinkertaisesti tulostaa "Hello, world!" ohjelman lokeihin, kun sitä kutsutaan.

Komennon cargo build-sbf suorittaminen luo käännetyn ohjelman sijaintiin /target/deploy/<program_name>.so.

src/lib.rs
use solana_program::{
account_info::AccountInfo, entrypoint, entrypoint::ProgramResult, msg, pubkey::Pubkey,
};
entrypoint!(process_instruction);
pub fn process_instruction(
_program_id: &Pubkey,
_accounts: &[AccountInfo],
_instruction_data: &[u8],
) -> ProgramResult {
msg!("Hello, world!");
Ok(())
}
#[cfg(test)]
mod tests {
use mollusk_svm::{result::Check, Mollusk};
use solana_sdk::{instruction::Instruction, pubkey::Pubkey};
#[test]
fn test_hello_world() {
let program_id = Pubkey::new_unique();
let mollusk = Mollusk::new(&program_id, "target/deploy/hello_world");
let instruction = Instruction::new_with_bytes(program_id, &[], vec![]);
mollusk.process_and_validate_instruction(&instruction, &[], &[Check::success()]);
}
}

Solana-ohjelman testaamiseksi Molluskilla:

  1. Luo Mollusk instanssi - Alusta Mollusk ohjelmatunnuksella ja käännetyn ohjelman polulla (.so tiedosto)
  2. Rakenna käsky - Luo käsky ohjelman kutsumiseksi
  3. Käsittele ja validoi - Käsittele käsky Molluskin avulla ja validoi tulos
src/lib.rs
#[cfg(test)]
mod tests {
use mollusk_svm::{result::Check, Mollusk};
use solana_sdk::{instruction::Instruction, pubkey::Pubkey};
#[test]
fn test_hello_world() {
let program_id = Pubkey::new_unique();
let mollusk = Mollusk::new(&program_id, "target/deploy/hello_world");
let instruction = Instruction::new_with_bytes(program_id, &[], vec![]);
mollusk.process_and_validate_instruction(&instruction, &[], &[Check::success()]);
}
}

Suorittaaksesi testin, aja cargo test.

Kun testi suoritetaan onnistuneesti, näet seuraavankaltaisen tulosteen:

Terminal
running 1 test
[2025-09-22T19:25:50.427685000Z DEBUG solana_runtime::message_processor::stable_log] Program 11157t3sqMV725NVRLrVQbAu98Jjfk1uCKehJnXXQs invoke [1]
[2025-09-22T19:25:50.429669000Z DEBUG solana_runtime::message_processor::stable_log] Program log: Hello, world!
[2025-09-22T19:25:50.429690000Z DEBUG solana_runtime::message_processor::stable_log] Program 11157t3sqMV725NVRLrVQbAu98Jjfk1uCKehJnXXQs consumed 211 of 1400000 compute units
[2025-09-22T19:25:50.429726000Z DEBUG solana_runtime::message_processor::stable_log] Program 11157t3sqMV725NVRLrVQbAu98Jjfk1uCKehJnXXQs success
test tests::test_hello_world ... ok
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.02s
Doc-tests hello_world

Hello World -ohjelma

Tämä esimerkki havainnollistaa, miten testataan perus-Solana-ohjelmaa Molluskin avulla. Ohjelma yksinkertaisesti tulostaa "Hello, world!" ohjelman lokeihin, kun sitä kutsutaan.

Komennon cargo build-sbf suorittaminen luo käännetyn ohjelman sijaintiin /target/deploy/<program_name>.so.

Solana-ohjelman testaamiseksi Molluskilla:

  1. Luo Mollusk instanssi - Alusta Mollusk ohjelmatunnuksella ja käännetyn ohjelman polulla (.so tiedosto)
  2. Rakenna käsky - Luo käsky ohjelman kutsumiseksi
  3. Käsittele ja validoi - Käsittele käsky Molluskin avulla ja validoi tulos
src/lib.rs
#[cfg(test)]
mod tests {
use mollusk_svm::{result::Check, Mollusk};
use solana_sdk::{instruction::Instruction, pubkey::Pubkey};
#[test]
fn test_hello_world() {
let program_id = Pubkey::new_unique();
let mollusk = Mollusk::new(&program_id, "target/deploy/hello_world");
let instruction = Instruction::new_with_bytes(program_id, &[], vec![]);
mollusk.process_and_validate_instruction(&instruction, &[], &[Check::success()]);
}
}

Suorittaaksesi testin, aja cargo test.

Kun testi suoritetaan onnistuneesti, näet seuraavankaltaisen tulosteen:

Terminal
running 1 test
[2025-09-22T19:25:50.427685000Z DEBUG solana_runtime::message_processor::stable_log] Program 11157t3sqMV725NVRLrVQbAu98Jjfk1uCKehJnXXQs invoke [1]
[2025-09-22T19:25:50.429669000Z DEBUG solana_runtime::message_processor::stable_log] Program log: Hello, world!
[2025-09-22T19:25:50.429690000Z DEBUG solana_runtime::message_processor::stable_log] Program 11157t3sqMV725NVRLrVQbAu98Jjfk1uCKehJnXXQs consumed 211 of 1400000 compute units
[2025-09-22T19:25:50.429726000Z DEBUG solana_runtime::message_processor::stable_log] Program 11157t3sqMV725NVRLrVQbAu98Jjfk1uCKehJnXXQs success
test tests::test_hello_world ... ok
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.02s
Doc-tests hello_world
lib.rs
hello_world.so
Cargo.toml
use solana_program::{
account_info::AccountInfo, entrypoint, entrypoint::ProgramResult, msg, pubkey::Pubkey,
};
entrypoint!(process_instruction);
pub fn process_instruction(
_program_id: &Pubkey,
_accounts: &[AccountInfo],
_instruction_data: &[u8],
) -> ProgramResult {
msg!("Hello, world!");
Ok(())
}
#[cfg(test)]
mod tests {
use mollusk_svm::{result::Check, Mollusk};
use solana_sdk::{instruction::Instruction, pubkey::Pubkey};
#[test]
fn test_hello_world() {
let program_id = Pubkey::new_unique();
let mollusk = Mollusk::new(&program_id, "target/deploy/hello_world");
let instruction = Instruction::new_with_bytes(program_id, &[], vec![]);
mollusk.process_and_validate_instruction(&instruction, &[], &[Check::success()]);
}
}

Mollusk -rakenne tarjoaa yksinkertaisen rajapinnan Solana-ohjelmien testaamiseen. Kaikkia kenttiä voidaan muokata muutaman apumetodin avulla, mutta käyttäjät voivat myös suoraan käyttää ja muokata niitä, jos he haluavat enemmän hallintaa.

Alustaaksesi Molluskin oletusinstanssilla käytä Mollusk::default -metodia.

Example
// Default instance with no custom programs
let mollusk = Mollusk::default();

Alustaaksesi Molluskin tietyllä ohjelmalla käytä Mollusk::new -metodia.

Example
// Initialize Mollusk with a specific program from a file path
let program_id = Pubkey::new_unique();
let mollusk = Mollusk::new(&program_id, "target/deploy/my_program");

Lisätäksesi ohjelman Molluskiin käytä Mollusk::add_program -metodia.

Example
let mollusk = Mollusk::default();
let program_id = Pubkey::new_unique();
// Add a program to Mollusk
mollusk.add_program(
&program_id,
"target/deploy/my_program",
&bpf_loader_upgradeable::id(),
);

Kun annat tiedostopolun, älä sisällytä .so -päätettä. Esimerkiksi "path/to/my_program" on oikein, mutta "path/to/my_program.so" ei ole.

Ohjeiden käsittely

Mollusk tarjoaa neljä päämetodia ohjeiden käsittelyyn:

MetodiKuvaus
process_instructionKäsittelee ohjeen ja palauttaa tuloksen.
process_and_validate_instructionKäsittelee ohjeen ja suorittaa sarjan tarkistuksia tulokselle, kaatuen jos jokin tarkistus epäonnistuu.
process_instruction_chainKäsittelee useita ohjeita ja palauttaa tuloksen.
process_and_validate_instruction_chainKäsittelee useita ohjeita ja suorittaa sarjan tarkistuksia jokaiselle tulokselle, kaatuen jos jokin tarkistus epäonnistuu.

InstructionResult sisältää käsitellyn ohjeen tiedot.

Yksittäinen ohje

Käytä process_instruction -metodia käsitelläksesi yksittäisen ohjeen ilman tarkistuksia tulokselle. Voit manuaalisesti validoida tulokset käsittelyn jälkeen.

Method Signature
pub fn process_instruction(
&self,
instruction: &Instruction,
accounts: &[(Pubkey, Account)],
) -> InstructionResult

Seuraava esimerkki käsittelee SOL-siirto-ohjeen ilman validointitarkistuksia.

Alla olevat esimerkit suorittavat Molluskin main funktiossa havainnollistamistarkoituksessa. Käytännössä käytät Molluskia tyypillisesti testimoduulissa, joka on merkitty #[test] attribuutilla.

Single Instruction
use {
mollusk_svm::Mollusk,
solana_sdk::{account::Account, pubkey::Pubkey, system_instruction, system_program},
};
fn main() {
// Initialize Mollusk
let mollusk = Mollusk::default();
// Set up accounts
let sender = Pubkey::new_unique();
let recipient = Pubkey::new_unique();
let initial_lamports = 1_000_000;
let transfer_amount = 250_000;
// Create transfer instruction
let instruction = system_instruction::transfer(&sender, &recipient, transfer_amount);
// Define initial account states
let accounts = vec![
(
sender,
Account {
lamports: initial_lamports,
data: vec![],
owner: system_program::id(),
executable: false,
rent_epoch: 0,
},
),
(
recipient,
Account {
lamports: 0,
data: vec![],
owner: system_program::id(),
executable: false,
rent_epoch: 0,
},
),
];
// Process the instruction
let result = mollusk.process_instruction(&instruction, &accounts);
println!("{:#?}", result);
// Check the result
assert!(result.program_result.is_ok());
assert_eq!(result.get_account(&sender).unwrap().lamports, 750_000);
assert_eq!(result.get_account(&recipient).unwrap().lamports, 250_000);
}
Console
Click to execute the code.

Yksittäinen ohje tarkistuksilla

Käytä process_and_validate_instruction metodia käsitelläksesi yksittäisen ohjeen validointitarkistuksilla. Tämä metodi aiheuttaa paniikkitilan, jos jokin tarkistus epäonnistuu.

Method Signature
pub fn process_and_validate_instruction(
&self,
instruction: &Instruction,
accounts: &[(Pubkey, Account)],
checks: &[Check],
) -> InstructionResult

Seuraava esimerkki käsittelee SOL-siirto-ohjeen validointitarkistuksilla.

With Validation
use {
mollusk_svm::{Mollusk, result::Check},
solana_sdk::{account::Account, pubkey::Pubkey, system_instruction, system_program},
};
fn main() {
let mollusk = Mollusk::default();
let sender = Pubkey::new_unique();
let recipient = Pubkey::new_unique();
let initial_lamports = 1_000_000;
let transfer_amount = 250_000;
let instruction = system_instruction::transfer(&sender, &recipient, transfer_amount);
let accounts = vec![
(
sender,
Account {
lamports: initial_lamports,
data: vec![],
owner: system_program::id(),
executable: false,
rent_epoch: 0,
},
),
(
recipient,
Account {
lamports: 0,
data: vec![],
owner: system_program::id(),
executable: false,
rent_epoch: 0,
},
),
];
// Define validation checks
let checks = vec![
Check::success(),
Check::account(&sender)
.lamports(750_000)
.build(),
Check::account(&recipient)
.lamports(250_000)
.build(),
];
// Process and validate (will panic if any check fails)
let result = mollusk.process_and_validate_instruction(&instruction, &accounts, &checks);
println!("{:#?}", result);
}
Console
Click to execute the code.

Useita ohjeita

Käytä process_instruction_chain metodia käsitelläksesi useita ohjeita peräkkäin ilman validointitarkistuksia.

Method Signature
pub fn process_instruction_chain(
&self,
instructions: &[Instruction],
accounts: &[(Pubkey, Account)],
) -> InstructionResult

Seuraava esimerkki käsittelee kaksi SOL-siirto-ohjetta ilman validointitarkistuksia.

Multiple Instructions
use {
mollusk_svm::Mollusk,
solana_sdk::{account::Account, pubkey::Pubkey, system_instruction, system_program},
};
fn main() {
let mollusk = Mollusk::default();
// Set up accounts
let alice = Pubkey::new_unique();
let bob = Pubkey::new_unique();
let charlie = Pubkey::new_unique();
let initial_lamports = 1_000_000;
// Create chain of transfers
let instructions = vec![
system_instruction::transfer(&alice, &bob, 300_000), // Alice -> Bob
system_instruction::transfer(&bob, &charlie, 100_000), // Bob -> Charlie
];
let accounts = vec![
(
alice,
Account {
lamports: initial_lamports,
data: vec![],
owner: system_program::id(),
executable: false,
rent_epoch: 0,
},
),
(
bob,
Account {
lamports: 0,
data: vec![],
owner: system_program::id(),
executable: false,
rent_epoch: 0,
},
),
(
charlie,
Account {
lamports: 0,
data: vec![],
owner: system_program::id(),
executable: false,
rent_epoch: 0,
},
),
];
// Process the instruction chain
let result = mollusk.process_instruction_chain(&instructions, &accounts);
println!("{:#?}", result);
// Final balances: Alice=700K, Bob=200K, Charlie=100K
assert_eq!(result.get_account(&alice).unwrap().lamports, 700_000);
assert_eq!(result.get_account(&bob).unwrap().lamports, 200_000);
assert_eq!(result.get_account(&charlie).unwrap().lamports, 100_000);
}
Console
Click to execute the code.

Useita ohjeita tarkistuksilla

Käytä process_and_validate_instruction_chain metodia käsitelläksesi useita ohjeita validointitarkistuksilla jokaisen ohjeen jälkeen. Jokaisella ohjeella on omat tarkistuksensa, joiden on läpäistävä.

Method Signature
pub fn process_and_validate_instruction_chain(
&self,
instructions: &[(&Instruction, &[Check])],
accounts: &[(Pubkey, Account)],
) -> InstructionResult

Seuraava esimerkki käsittelee ketjun, jossa on kaksi SOL-siirto-ohjetta validointitarkistuksilla jokaisen ohjeen jälkeen.

With Validation
use {
mollusk_svm::{result::Check, Mollusk},
solana_sdk::{account::Account, pubkey::Pubkey, system_instruction, system_program},
};
fn main() {
let mollusk = Mollusk::default();
// Create accounts
let alice = Pubkey::new_unique();
let bob = Pubkey::new_unique();
let charlie = Pubkey::new_unique();
let initial_lamports = 1_000_000;
// Create transfer instructions
let transfer1 = system_instruction::transfer(&alice, &bob, 300_000);
let transfer2 = system_instruction::transfer(&bob, &charlie, 100_000);
// Initial accounts
let accounts = vec![
(
alice,
Account {
lamports: initial_lamports,
data: vec![],
owner: system_program::id(),
executable: false,
rent_epoch: 0,
},
),
(
bob,
Account {
lamports: 0,
data: vec![],
owner: system_program::id(),
executable: false,
rent_epoch: 0,
},
),
(
charlie,
Account {
lamports: 0,
data: vec![],
owner: system_program::id(),
executable: false,
rent_epoch: 0,
},
),
];
// Define checks for each instruction
let checks_after_transfer1 = vec![
Check::success(),
Check::account(&alice)
.lamports(700_000) // 1M - 300K
.build(),
Check::account(&bob)
.lamports(300_000) // 0 + 300K
.build(),
Check::account(&charlie)
.lamports(0) // Unchanged
.build(),
];
let checks_after_transfer2 = vec![
Check::success(),
Check::account(&alice)
.lamports(700_000) // Unchanged from previous
.build(),
Check::account(&bob)
.lamports(200_000) // 300K - 100K
.build(),
Check::account(&charlie)
.lamports(100_000) // 0 + 100K
.build(),
];
// Process with validation at each step
let instruction_and_checks = [
(&transfer1, checks_after_transfer1.as_slice()),
(&transfer2, checks_after_transfer2.as_slice()),
];
// Execute chain (panics if any check fails)
let result = mollusk.process_and_validate_instruction_chain(&instruction_and_checks, &accounts);
println!("{:#?}", result);
}
Console
Click to execute the code.

Validointitarkistukset

Mollusk tarjoaa joukon apumetodeja käsitellyn ohjeen tulosten tarkistamiseen.

Example
use mollusk_svm::result::Check;

Käytä seuraavia metodeja ohjeiden tulosten validointiin:

Example
// Program execution succeeded
Check::success()
// Program returned specific error
Check::err(ProgramError::InvalidArgument)
// Instruction level error
Check::instruction_err(InstructionError::InsufficientFunds)
// Check with specific program result
Check::program_result(ProgramResult::Success)
// Compute units consumed
Check::compute_units(1000)
// Execution time
Check::time(100)
// Return data from instruction execution
Check::return_data(&[1, 2, 3, 4])

Käytä seuraavia tilin tilojen validointiin:

Example
// Single account validation
Check::account(&pubkey)
.lamports(1_000_000) // Exact lamports
.owner(&program_id) // Account owner
.data(&expected_data) // Exact data match
.data_slice(8, &[1, 2, 3]) // Partial data match at offset
.executable(false) // Executable flag
.space(100) // Account data size
.closed() // Account is closed (0 lamports)
.rent_exempt() // Account is rent-exempt
.build()
// Check all accounts are rent exempt
Check::all_rent_exempt()

Pysyvä tilin tila

MolluskContext on kääre Mollusk:n ympärillä, joka ylläpitää tilin tilaa useiden ohjekutsujen välillä account_store:n kautta. Ohjeiden käsittelymetodit ovat identtisiä Mollusk:n kanssa.

Toisin kuin Mollusk, joka vaatii accounts:n välittämistä jokaiselle metodille (esim. process_instruction), MolluskContext hallinnoi tilejä sisäisesti account_store:n kautta. Tämä poistaa tarpeen accounts -parametrille ohjeiden käsittelyssä.

Luo account_store käyttämällä with_context -metodia:

Example
use std::collections::HashMap;
use solana_sdk::{account::Account, pubkey::Pubkey, system_program};
use mollusk_svm::Mollusk;
let mollusk = Mollusk::default();
let account_address = Pubkey::new_unique();
let mut account_store = HashMap::new();
account_store.insert(
account_address,
Account {
lamports: 1_000_000,
data: vec![],
owner: system_program::id(),
executable: false,
rent_epoch: 0,
},
);
let context = mollusk.with_context(account_store);

Seuraava esimerkki käsittelee kaksi erillistä SOL-siirto-ohjetta, joiden välillä tilin tila säilyy account_store:n kautta.

Stateful Testing
use {
mollusk_svm::Mollusk,
solana_sdk::{account::Account, pubkey::Pubkey, system_instruction, system_program},
std::collections::HashMap,
};
fn main() {
// Initialize Mollusk
let mollusk = Mollusk::default();
// Create accounts
let sender = Pubkey::new_unique();
let recipient = Pubkey::new_unique();
// Create account store with initial balances
let mut account_store = HashMap::new();
account_store.insert(
sender,
Account {
lamports: 1_000_000,
data: vec![],
owner: system_program::id(),
executable: false,
rent_epoch: 0,
},
);
account_store.insert(
recipient,
Account {
lamports: 0,
data: vec![],
owner: system_program::id(),
executable: false,
rent_epoch: 0,
},
);
// Create a stateful context
let context = mollusk.with_context(account_store);
// First transfer: 200,000 lamports
let instruction1 = system_instruction::transfer(&sender, &recipient, 200_000);
context.process_instruction(&instruction1);
// Second transfer: 100,000 lamports (state persists from first transfer)
let instruction2 = system_instruction::transfer(&sender, &recipient, 100_000);
context.process_instruction(&instruction2);
// Check final balances
let store = context.account_store.borrow();
let sender_account = store.get(&sender).unwrap();
let recipient_account = store.get(&recipient).unwrap();
println!("Sender: {:#?}", sender_account);
println!("Recipient: {:#?}", recipient_account);
}
Console
Click to execute the code.

Mollusk Sysvars

Mollusk tarjoaa mukautetun Sysvars -rakenteen sen arvojen muokkaamiseen testausta varten.

Käytä warp_to_slot -metodia päivittääksesi sysvar-kelloa simuloidaksesi ajan siirtymistä eteen- tai taaksepäin tiettyyn slotiin.

Warp to Slot
use mollusk_svm::Mollusk;
fn main() {
// Initialize Mollusk
let mut mollusk = Mollusk::default();
// Show initial slot
println!("Initial slot: {}", mollusk.sysvars.clock.slot);
// Warp to slot 1000
mollusk.warp_to_slot(100);
println!("After warp: {}", mollusk.sysvars.clock.slot);
// Warp to slot 10
mollusk.warp_to_slot(10);
println!("After second warp: {}", mollusk.sysvars.clock.slot);
}
Console
Click to execute the code.

Seuraava esimerkki näyttää, miten Mollusk sysvaria voi muokata suoraan käyttämällä sysvars -kenttää rent-parametrien muuttamiseen. Voit muokata muita sysvar-arvoja samalla tavalla.

Modify Sysvars
use {mollusk_svm::Mollusk, solana_sdk::rent::Rent};
fn main() {
let mut mollusk = Mollusk::default();
// Show default rent
println!(
"Default rent exemption for 1000 bytes: {} lamports",
mollusk.sysvars.rent.minimum_balance(1000)
);
// Customize rent parameters
mollusk.sysvars.rent = Rent {
lamports_per_byte_year: 1,
exemption_threshold: 1.0,
burn_percent: 0,
};
// Show custom rent
println!(
"Custom rent exemption for 1000 bytes: {} lamports",
mollusk.sysvars.rent.minimum_balance(1000)
);
}
Console
Click to execute the code.

Laskentayksikön suorituskyvyn mittaus

MolluskComputeUnitBencher seuraa ohjelman käskyjen laskentayksikköjen käyttöä. Tulokset kirjoitetaan markdown-tiedostoon.

Vaatii mollusk-svm-bencher riippuvuutena.

Seuraava esimerkki mittaa SOL-siirtokäskyn laskentayksikköjen käyttöä.

Benchmark Compute Units
use {
mollusk_svm::Mollusk,
mollusk_svm_bencher::MolluskComputeUnitBencher,
solana_sdk::{account::Account, pubkey::Pubkey, system_instruction, system_program},
};
fn main() {
// Initialize Mollusk
let mollusk = Mollusk::default();
// Create test accounts
let sender = Pubkey::new_unique();
let receiver = Pubkey::new_unique();
// Transfer instruction
let transfer = system_instruction::transfer(&sender, &receiver, 100_000);
let accounts = vec![
(
sender,
Account {
lamports: 1_000_000,
data: vec![],
owner: system_program::id(),
executable: false,
rent_epoch: 0,
},
),
(
receiver,
Account {
lamports: 0,
data: vec![],
owner: system_program::id(),
executable: false,
rent_epoch: 0,
},
),
];
// Run benchmark
MolluskComputeUnitBencher::new(mollusk)
.bench(("transfer", &transfer, &accounts))
.must_pass(true)
.out_dir("./target/benches")
.execute();
}

Suorituskykytestien tulokset kirjoitetaan määritettyyn out_dir markdown-tiedostona nimeltä compute_units.md.

comput_units.md
#### 2025-09-19 22:28:53.691839 UTC
Solana CLI Version: solana-cli 2.2.20 (src:dabc99a5; feat:3073396398,
client:Agave)
| Name | CUs | Delta |
| -------- | --- | ------- |
| transfer | 150 | - new - |

Token Program -testaus

Käytä mollusk-svm-programs-token pakettia lisätäksesi Token Program, token2022-ohjelman (Token Extensions) ja Associated Token Program Molluskiin testausta varten.

Example
use {
mollusk_svm::Mollusk,
mollusk_svm_programs_token::{associated_token, token, token2022},
};
let mut mollusk = Mollusk::default();
// Add SPL Token Program
token::add_program(&mut mollusk);
// Add SPL Token-2022 Program
token2022::add_program(&mut mollusk);
// Add Associated Token Account Program
associated_token::add_program(&mut mollusk);

Seuraava esimerkki havainnollistaa token-siirron testaamista Molluskin avulla.

Alla oleva esimerkki määrittelee testitilit manuaalisesti havainnollistamistarkoituksessa. mollusk-svm-programs-token sisältää myös apufunktioita mint- ja token-tilien luomiseen.

Token Transfer Example
use {
mollusk_svm::{result::Check, Mollusk},
mollusk_svm_programs_token::token,
solana_sdk::{account::Account, program_pack::Pack, pubkey::Pubkey},
spl_token::{
instruction::transfer_checked,
state::{Account as TokenAccount, Mint},
},
};
fn main() {
// Initialize Mollusk with Token program
let mut mollusk = Mollusk::default();
token::add_program(&mut mollusk);
// Create account keys
let mint = Pubkey::new_unique();
let source = Pubkey::new_unique();
let destination = Pubkey::new_unique();
let authority = Pubkey::new_unique();
// Token configuration
let decimals = 6;
let transfer_amount = 1_000_000; // 1 token with 6 decimals
let initial_balance = 10_000_000; // 10 tokens
// Calculate rent-exempt minimums
let mint_rent = mollusk.sysvars.rent.minimum_balance(Mint::LEN);
let account_rent = mollusk.sysvars.rent.minimum_balance(TokenAccount::LEN);
// Create mint account
let mut mint_data = vec![0u8; Mint::LEN];
Mint::pack(
Mint {
mint_authority: Some(authority).into(),
supply: initial_balance,
decimals,
is_initialized: true,
freeze_authority: None.into(),
},
&mut mint_data,
)
.unwrap();
// Create source token account
let mut source_data = vec![0u8; TokenAccount::LEN];
TokenAccount::pack(
TokenAccount {
mint,
owner: authority,
amount: initial_balance,
delegate: None.into(),
state: spl_token::state::AccountState::Initialized,
is_native: None.into(),
delegated_amount: 0,
close_authority: None.into(),
},
&mut source_data,
)
.unwrap();
// Create destination token account
let mut destination_data = vec![0u8; TokenAccount::LEN];
TokenAccount::pack(
TokenAccount {
mint,
owner: Pubkey::new_unique(),
amount: 0,
delegate: None.into(),
state: spl_token::state::AccountState::Initialized,
is_native: None.into(),
delegated_amount: 0,
close_authority: None.into(),
},
&mut destination_data,
)
.unwrap();
// Setup accounts for transfer_checked
let accounts = vec![
(
source,
Account {
lamports: account_rent,
data: source_data,
owner: token::ID,
executable: false,
rent_epoch: 0,
},
),
(
mint,
Account {
lamports: mint_rent,
data: mint_data,
owner: token::ID,
executable: false,
rent_epoch: 0,
},
),
(
destination,
Account {
lamports: account_rent,
data: destination_data,
owner: token::ID,
executable: false,
rent_epoch: 0,
},
),
(
authority,
Account {
lamports: 1_000_000,
data: vec![],
owner: Pubkey::default(),
executable: false,
rent_epoch: 0,
},
),
];
// Create transfer_checked instruction
let instruction = transfer_checked(
&token::ID,
&source,
&mint,
&destination,
&authority,
&[],
transfer_amount,
decimals,
)
.unwrap();
// Expected balances after transfer
let expected_source_balance = (initial_balance - transfer_amount).to_le_bytes();
let expected_dest_balance = transfer_amount.to_le_bytes();
// Define validation checks
let checks = vec![
Check::success(),
Check::account(&source)
.data_slice(64, &expected_source_balance) // Token amount is at offset 64
.build(),
Check::account(&destination)
.data_slice(64, &expected_dest_balance)
.build(),
];
// Process and validate the instruction
let result = mollusk.process_and_validate_instruction(&instruction, &accounts, &checks);
println!("{:#?}", result);
// Deserialize token account data
let source_account = result.get_account(&source).unwrap();
let source_token = TokenAccount::unpack(&source_account.data).unwrap();
println!("Source Token Account: {:#?}", source_token);
let destination_account = result.get_account(&destination).unwrap();
let dest_token = TokenAccount::unpack(&destination_account.data).unwrap();
println!("Destination Token Account: {:#?}", dest_token);
}
Console
Click to execute the code.

Is this page helpful?

Sisällysluettelo

Muokkaa sivua