Skip to content

Commit

Permalink
Update docs (#11)
Browse files Browse the repository at this point in the history
  • Loading branch information
buffalojoec authored Jun 23, 2024
1 parent 6d150c9 commit 5331efd
Show file tree
Hide file tree
Showing 11 changed files with 113 additions and 30 deletions.
10 changes: 5 additions & 5 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ members = [
]
resolver = "2"

[workspace.package]
authors = ["Joe Caulfield <[email protected]>"]
repository = "https://github.com/buffalojoec/mollusk"
license = "../license"
edition = "2021"

[workspace.dependencies]
bincode = "1.3.3"
num-format = "0.4.4"
Expand Down
77 changes: 67 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
# Mollusk

Solana program testing tools.
SVM program test harness.

## Harness

The harness is designed to directly invoke the loaded executable program using
the BPF Loader, bypassing any transaction sanitization and runtime checks, and
instead directly processing the instruction with the BPF Loader.

Example:

```rust
let program_id = Pubkey::new_unique();
let key1 = Pubkey::new_unique();
Expand All @@ -31,7 +29,47 @@ let accounts = vec![

let mollusk = Mollusk::new(program_id, "my_program");

let result = mollusk.process_instruction(instruction, accounts);
let result = mollusk.process_instruction(&instruction, &accounts);
```

You can also use the `Checks` API provided by Mollusk for easy post-execution
checks, rather than writing them manually. The API method
`process_and_validate_instruction` will still return the result, allowing you
to perform further checks if you desire.

> Note: `Mollusk::default()` will use the System program as the program to
> invoke.
```rust
let sender = Pubkey::new_unique();
let recipient = Pubkey::new_unique();

let base_lamports = 100_000_000u64;
let transfer_amount = 42_000u64;

let instruction = system_instruction::transfer(&sender, &recipient, transfer_amount);
let accounts = [
(
sender,
AccountSharedData::new(base_lamports, 0, &system_program::id()),
),
(
recipient,
AccountSharedData::new(base_lamports, 0, &system_program::id()),
),
];
let checks = vec![
Check::success(),
Check::compute_units(system_processor::DEFAULT_COMPUTE_UNITS),
Check::account(&sender)
.lamports(base_lamports - transfer_amount)
.build(),
Check::account(&recipient)
.lamports(base_lamports + transfer_amount)
.build(),
];

Mollusk::default().process_and_validate_instruction(&instruction, &accounts, &checks);
```

## Bencher
Expand All @@ -42,18 +80,37 @@ compute unit usage.
Example:

```rust
// If using with `cargo bench`, tell Mollusk where to find the program.
std::env::set_var("SBF_OUT_DIR", "../target/deploy");

// Optionally disable logging.
solana_logger::setup_with("");

/* Instruction & accounts setup ... */

let mollusk = Mollusk::new(&program_id, "my_program");

MolluskComputeUnitBencher::new(mollusk)
.benchmark(BENCHMARK_COMPUTE_UNITS)
.bench("bench1", instruction1, accounts1)
.bench("bench2", instruction2, accounts2)
.bench("bench3", instruction3, accounts3)
.iterations(100)
.bench(("bench0", &instruction0, &accounts0))
.bench(("bench1", &instruction1, &accounts1))
.bench(("bench2", &instruction2, &accounts2))
.bench(("bench3", &instruction3, &accounts3))
.bench(("bench4", &instruction4, &accounts4))
.bench(("bench5", &instruction5, &accounts5))
.bench(("bench6", &instruction6, &accounts6))
.must_pass(true)
.out_dir("../target/benches")
.execute();
```

You can invoke this benchmark test with `cargo bench`.
You can invoke this benchmark test with `cargo bench`. Don't forget to add a
bench to your project's `Cargo.toml`.

```toml
[[bench]]
name = "compute_units"
harness = false
```

Mollusk will output bench details to the output directory in both JSON and
Markdown.
Expand Down
13 changes: 9 additions & 4 deletions bencher/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
[package]
name = "mollusk-bencher"
version = "0.1.0"
edition = "2021"
name = "mollusk-svm-bencher"
version = "0.0.1"
description = "SVM program bench harness."
documentation = "https://docs.rs/mollusk-svm-bencher"
authors = { workspace = true }
repository = { workspace = true }
license = { workspace = true }
edition = { workspace = true }

[dependencies]
chrono = "0.4.38"
mollusk = { path = "../harness" }
num-format = { workspace = true }
serde_json = { workspace = true }
mollusk-svm = { path = "../harness" }
solana-sdk = { workspace = true }

[dev-dependencies]
Expand Down
11 changes: 10 additions & 1 deletion bencher/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,18 @@
mod result;

use {
mollusk::{result::ProgramResult, Mollusk},
mollusk_svm::{result::ProgramResult, Mollusk},
result::{write_results, MolluskComputeUnitBenchResult},
solana_sdk::{account::AccountSharedData, instruction::Instruction, pubkey::Pubkey},
std::path::PathBuf,
};

/// A bench is a tuple of a name, an instruction, and a list of accounts.
pub type Bench<'a> = (&'a str, &'a Instruction, &'a [(Pubkey, AccountSharedData)]);

/// Mollusk's compute unit bencher.
///
/// Allows developers to bench test compute unit usage on their programs.
pub struct MolluskComputeUnitBencher<'a> {
benches: Vec<Bench<'a>>,
mollusk: Mollusk,
Expand All @@ -19,6 +23,7 @@ pub struct MolluskComputeUnitBencher<'a> {
}

impl<'a> MolluskComputeUnitBencher<'a> {
/// Create a new bencher, to which benches and configurations can be added.
pub fn new(mollusk: Mollusk) -> Self {
let mut out_dir = PathBuf::from(std::env::var("CARGO_MANIFEST_DIR").unwrap());
out_dir.push("benches");
Expand All @@ -30,21 +35,25 @@ impl<'a> MolluskComputeUnitBencher<'a> {
}
}

/// Add a bench to the bencher.
pub fn bench(mut self, bench: Bench<'a>) -> Self {
self.benches.push(bench);
self
}

/// Set whether the bencher should panic if a program execution fails.
pub fn must_pass(mut self, must_pass: bool) -> Self {
self.must_pass = must_pass;
self
}

/// Set the output directory for the results.
pub fn out_dir(mut self, out_dir: &str) -> Self {
self.out_dir = PathBuf::from(out_dir);
self
}

/// Execute the benches.
pub fn execute(&mut self) {
let bench_results = std::mem::take(&mut self.benches)
.into_iter()
Expand Down
4 changes: 3 additions & 1 deletion bencher/src/result.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
//! Compute unit benchmarking results and checks.

use {
chrono::{DateTime, Utc},
mollusk::result::InstructionResult,
mollusk_svm::result::InstructionResult,
num_format::{Locale, ToFormattedString},
std::path::Path,
};
Expand Down
4 changes: 2 additions & 2 deletions bencher/tests/markdown.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use {
mollusk::Mollusk,
mollusk_bencher::MolluskComputeUnitBencher,
mollusk_svm::Mollusk,
mollusk_svm_bencher::MolluskComputeUnitBencher,
solana_sdk::{instruction::Instruction, pubkey::Pubkey},
};

Expand Down
12 changes: 8 additions & 4 deletions harness/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
[package]
name = "mollusk"
version = "0.1.0"
edition = "2021"
name = "mollusk-svm"
version = "0.0.1"
description = "SVM program test harness."
documentation = "https://docs.rs/mollusk-svm"
authors = { workspace = true }
repository = { workspace = true }
license = { workspace = true }
edition = { workspace = true }

[dependencies]
bincode = { workspace = true }
Expand All @@ -11,7 +16,6 @@ solana-system-program = { workspace = true }
solana-sdk = { workspace = true }
solana-logger = { workspace = true }


[[bench]]
name = "ips"
harness = false
Expand Down
2 changes: 1 addition & 1 deletion harness/benches/ips.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! Benches Mollusk invocation (instructions per second)
use {
criterion::{criterion_group, criterion_main, Criterion, Throughput},
mollusk::{result::Check, Mollusk},
mollusk_svm::{result::Check, Mollusk},
solana_sdk::{
account::AccountSharedData, native_token::LAMPORTS_PER_SOL, pubkey::Pubkey,
system_instruction, system_program,
Expand Down
2 changes: 1 addition & 1 deletion harness/tests/bpf_program.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use {
mollusk::{
mollusk_svm::{
program::{create_program_account, system_program_account},
result::Check,
Mollusk,
Expand Down
2 changes: 1 addition & 1 deletion harness/tests/system_program.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use {
mollusk::{result::Check, Mollusk},
mollusk_svm::{result::Check, Mollusk},
solana_sdk::{
account::AccountSharedData, instruction::InstructionError, pubkey::Pubkey,
system_instruction, system_program,
Expand Down

0 comments on commit 5331efd

Please sign in to comment.