Crates.io | trdelnik-cli |
lib.rs | trdelnik-cli |
version | 0.5.0 |
source | src |
created_at | 2022-07-14 10:16:38.162869 |
updated_at | 2023-08-28 16:43:13.121104 |
description | Trdelník is Rust based testing framework providing several convenient developer tools for testing Solana programs written in Anchor. |
homepage | |
repository | https://github.com/Ackee-Blockchain/trdelnik |
max_upload_size | |
id | 625615 |
size | 164,558 |
Trdelník is Rust based testing framework providing several convenient developer tools for testing Solana programs written in Anchor.
nightly
release)stable
release)cargo install trdelnik-cli
# or the specific version
cargo install --version <version> trdelnik-cli
# navigate to your project root directory
trdelnik init
# it will generate `.program_client` and `trdelnik-tests` directories with all the necessary files
trdelnik test
# want more?
trdelnik --help
// <my_project>/trdelnik-tests/tests/test.rs
// TODO: do not forget to add all necessary dependencies to the generated `trdelnik-tests/Cargo.toml`
use program_client::my_instruction;
use trdelnik_client::*;
use my_program;
#[throws]
#[fixture]
async fn init_fixture() -> Fixture {
// create a test fixture
let mut fixture = Fixture {
client: Client::new(system_keypair(0)),
// make sure your program is using a correct program ID
program: program_keypair(1),
state: keypair(42),
};
// deploy a tested program
fixture.deploy().await?;
// call instruction init
my_instruction::initialize(
&fixture.client,
fixture.state.pubkey(),
fixture.client.payer().pubkey(),
System::id(),
Some(fixture.state.clone()),
).await?;
fixture
}
#[trdelnik_test]
async fn test_happy_path(#[future] init_fixture: Result<Fixture>) {
let fixture = init_fixture.await?;
// call the instruction
my_instruction::do_something(
&fixture.client,
"dummy_string".to_owned(),
fixture.state.pubkey(),
None,
).await?;
// check the test result
let state = fixture.get_state().await?;
assert_eq!(state.something_changed, "yes");
}
Make sure your program is using a correct program ID in the derive_id!(...)
macro and inside Anchor.toml
.
If not, obtain the public key of a key pair you're using and replace it in these two places.
To get the program ID of a key pair (key pair's public key) the trdelnik key-pair
command can be used.
For example
$ trdelnik key-pair program 7
will print information about the key pair received from program_keypair(7)
.
pub struct MyStruct {
amount: u64,
}
// ...
pub fn my_instruction(ctx: Context<Ctx>, data: MyStruct) { /* ... */ }
.program_client
crate// .program_client/src/lib.rs
// DO NOT EDIT - automatically generated file
pub mod my_program_instruction {
use trdelnik_client::*;
use my_program::MyStruct; // add this import
// ...
}
use
statements won't be regenerated#[ignore]
macro to skip the test.#[trdelnik_test]
#[ignore]
async fn test() {}
Trdelnik
does not export anchor-spl
and spl-associated-token-account
, so you have to add it manually.# <my-project>/trdelnik-tests/Cargo.toml
# import the correct versions manually
anchor-spl = "0.28.0"
spl-associated-token-account = "2.0.0"
// <my-project>/trdelnik-tests/tests/test.rs
use anchor_spl::token::Token;
use spl_associated_token_account;
async fn init_fixture() -> Fixture {
// ...
let account = keypair(1);
let mint = keypair(2);
// constructs a token mint
client
.create_token_mint(&mint, mint.pubkey(), None, 0)
.await?;
// constructs associated token account
let token_account = client
.create_associated_token_account(&account, mint.pubkey())
.await?;
let associated_token_program = spl_associated_token_account::id();
// derives the associated token account address for the given wallet and mint
let associated_token_address = spl_associated_token_account::get_associated_token_address(&account.pubkey(), mint);
Fixture {
// ...
token_program: Token::id(),
}
}
trdelnik init
command generated a dummy test suite for you.Once you initialize Trdelnik in your Anchor project, you will find a fuzz test template in the trdelnik-tests/src/bin
folder that you can modify according to your needs or create new targets. Do not forget to install honggfuzz-rs using cargo install honggfuzz
.
# To run the fuzz test, execute this command from your terminal and replace <TARGET_NAME> with the name of your fuzz target (by default "fuzz_target")
trdelnik fuzz run <TARGET_NAME>
# To debug your fuzz target crash with parameters from a crash file
trdelnik fuzz run-debug <TARGET_NAME> <CRASH_FILE_PATH>
Under the hood Trdelnik uses honggfuzz-rs. You can pass parameters via environment variables. List of hongfuzz parameters can be found in honggfuzz usage documentation. For example:
# Time-out: 10 secs
# Number of concurrent fuzzing threads: 1
# Number of fuzzing iterations: 10000
# Display Solana logs in the terminal
HFUZZ_RUN_ARGS="-t 10 -n 1 -N 10000 -Q" trdelnik fuzz run <TARGET_NAME>
NOTE: If you will use the
solana-program-test
crate for fuzzing, creating a new test program usingProgramTest::new()
will create temporary folders in your/tmp
directory that will not be cleared in case your program panics. You might want to clear these folders manually.
Anchor
and Solana
versions specified in the table below.Trdelnik CLI | Anchor | Solana |
---|---|---|
latest |
~0.28.* |
=1.16.6 |
v0.4.0 |
~0.27.* |
>=1.15 |
v0.3.0 |
~0.25.* |
>=1.10 |
v0.2.0 |
~0.24.* |
>=1.9 |
The configuration variables can be edited in the Trdelnik.toml
file that'll be generated in the root of the project.
Name | Default value | Description |
---|---|---|
test.validator_startup_timeout |
10 000 | Time to wait for the solana-test-validator in milliseconds before failure |
Marinade Community Prize - winner of the Marinade grant for the 2022 Solana Riptide Hackathon.
Thank you for your interest in contributing to Trdelník! Please see the CONTRIBUTING.md to learn how.
This project is licensed under the MIT license.