From 0d28a5de7d83ca77a838f4485e5003269e983b25 Mon Sep 17 00:00:00 2001 From: andrejlukacovic <37964423+lukacan@users.noreply.github.com> Date: Fri, 16 Feb 2024 14:47:46 +0100 Subject: [PATCH] =?UTF-8?q?=F0=9F=A7=91=E2=80=8D=F0=9F=92=BB=20add=20help?= =?UTF-8?q?=20comment=20+=20update=20documentation=20(#120)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 🧑‍💻 add help comment for fuzz add command * 📝 update fuzzing.md for new folder structure * 📝 readme update --- Fuzzing.md | 36 ++++++++++++++++++---------------- README.md | 12 ++++++------ crates/cli/src/command/fuzz.rs | 1 + crates/cli/src/lib.rs | 4 ++-- 4 files changed, 28 insertions(+), 25 deletions(-) diff --git a/Fuzzing.md b/Fuzzing.md index 1d06d51b..6877d47c 100644 --- a/Fuzzing.md +++ b/Fuzzing.md @@ -25,16 +25,18 @@ trdelnik init The command will generate the required folder structure and fuzz test files: ```shell project-root -├── .trdelnik_client +├── .program_client ├── trdelnik-tests -│ ├── src # fuzz tests folder -│ │ ├── bin -│ │ │ └── fuzz_target.rs # the binary target of your fuzz test -│ │ ├── fuzz_instructions.rs # the definition of your fuzz test -│ │ ├── accounts_snapshots.rs # generated accounts deserialization methods -│ │ └── lib.rs -│ ├── tests # integration tests folder -│ └── Cargo.toml +│ ├── fuzz_tests # fuzz tests folder +│ │ ├── fuzz_0 # particular fuzz test +│ │ │ ├── accounts_snapshots.rs # generated accounts deserialization methods +│ │ │ ├── test_fuzz.rs # the binary target of your fuzz test +│ │ │ └── fuzz_instructions.rs # the definition of your fuzz test +│ │ ├── fuzz_1 +│ │ ├── fuzz_X # possible multiple fuzz tests +│ │ ├── fuzzing # compilations and crashes folder +│ │ └── Cargo.toml +│ ├── poc_tests # integration tests folder ├── Trdelnik.toml └── ... ``` @@ -43,7 +45,7 @@ project-root Once you have finished the implementation of `get_accounts` and `get_data` methods (see below), you can run the fuzz test as follows: ```shell -# Replace with the name of your fuzz target (by default "fuzz_target") +# Replace with the name of particular fuzz test (for example: "fuzz_0") trdelnik fuzz run ``` @@ -61,7 +63,7 @@ iterations = 1000 # Number of fuzzing iterations exit_upon_crash = true # Stop the fuzzer upon crash. ``` -Or you can pass any parameter via [environment variables](https://github.com/rust-fuzz/honggfuzz-rs#environment-variables). A list of hongfuzz parameters can be found in honggfuzz [usage documentation](https://github.com/google/honggfuzz/blob/master/docs/USAGE.md#cmdline---help). The parameters passed via environment variables have higher priority. For example: +Or you can pass any parameter via [environment variables](https://github.com/rust-fuzz/honggfuzz-rs#environment-variables). A list of hongfuzz parameters can be found in honggfuzz [usage documentation](https://github.com/google/honggfuzz/blob/master/docs/USAGE.md#cmdline---help). The parameters passed via **environment variables** have **higher priority**. For example: ```shell # Time-out: 10 secs # Number of concurrent fuzzing threads: 1 @@ -96,13 +98,13 @@ Some diagram states are labeled with emojis: ## Write a fuzz test At the current development stage, there are some manual steps required to make your fuzz test compile: -1. Add dependencies specific to your program to `trdelnik-tests/Cargo.toml` (such as anchor-spl etc.). -2. Add necessary `use` statements into `trdelnik-tests/src/accounts_snapshots.rs` to import missing types. +1. Add dependencies specific to your program to `trdelnik-tests/fuzz_tests/Cargo.toml` (such as anchor-spl etc.). +2. Add necessary `use` statements into `trdelnik-tests/fuzz_tests//accounts_snapshots.rs` to import missing types. ### Specify accounts to reuse Trdelnik fuzzer helps you to generate only a limited amount of pseudo-random accounts and reuse them in the instructions. Always generating only random accounts would in most cases lead to a situation where the fuzzer would be stuck because the accounts would be almost every time rejected by your Anchor program. Therefore it is necessary to specify, what accounts should be used and also limit the number of newly created accounts to reduce the space complexity. -Go to the `trdelnik-tests/src/fuzz_instructions.rs` file and complete the pre-generated `FuzzAccounts` structure. It contains all accounts used in your program. You have to determine, if the account is a signer, a PDA, a token account or program account. Than use the corresponding `AccountsStorage` types such as: +Go to the `trdelnik-tests/fuzz_tests//fuzz_instructions.rs` file and complete the pre-generated `FuzzAccounts` structure. It contains all accounts used in your program. You have to determine, if the account is a signer, a PDA, a token account or program account. Than use the corresponding `AccountsStorage` types such as: ```rust pub struct FuzzAccounts { signer: AccountsStorage, @@ -113,7 +115,7 @@ pub struct FuzzAccounts { ``` ### Specify instruction data -Trdelnik fuzzer generates random instruction data for you. Currently it is however required, that you manually assign the random fuzzer data to the instruction data. It is done using the `IxOps` trait and its method `get_data`. Go to the `trdelnik-tests/src/fuzz_instructions.rs` file and complete the pre-generated `get_data` methods for each instruction such as: +Trdelnik fuzzer generates random instruction data for you. Currently it is however required, that you manually assign the random fuzzer data to the instruction data. It is done using the `IxOps` trait and its method `get_data`. Go to the `trdelnik-tests/fuzz_tests//fuzz_instructions.rs` file and complete the pre-generated `get_data` methods for each instruction such as: ```rust fn get_data( &self, @@ -128,7 +130,7 @@ fn get_data( ``` ### Specify instruction accounts -Trdelnik fuzzer generates random indexes of accounts to use in each instruction. Each created account is saved in the `FuzzAccounts` structure which helps you to reuse already existing accounts. You are required to define, how these accounts should be created and which accounts should be passed to an instruction. It is done using the `IxOps` trait and its method `get_accounts`. Go to the `trdelnik-tests/src/fuzz_instructions.rs` file and complete the pre-generated `get_accounts` methods for each instruction such as: +Trdelnik fuzzer generates random indexes of accounts to use in each instruction. Each created account is saved in the `FuzzAccounts` structure which helps you to reuse already existing accounts. You are required to define, how these accounts should be created and which accounts should be passed to an instruction. It is done using the `IxOps` trait and its method `get_accounts`. Go to the `trdelnik-tests/fuzz_tests//fuzz_instructions.rs` file and complete the pre-generated `get_accounts` methods for each instruction such as: ```rust fn get_accounts( &self, @@ -188,7 +190,7 @@ fn check( ``` ### Customize instructions generation -It is possible to customize how the instructions are generated and which instructions will be executed at the beginning (`pre_ixs`), in the middle (`ixs`) and at the end (`post_ixs`) of each fuzz iteration. This can be useful for example if your program needs an initialization or you want to fuzz some specific program state. Go to the bin target file of your fuzz test and implement the corresponding optional method of the `FuzzDataBuilder` trait. For example, in order to always call the `initialize` instruction for the default fuzz target, modify the trait's implementation in `trdelnik-tests/src/bin/fuzz_target.rs` file as follows: +It is possible to customize how the instructions are generated and which instructions will be executed at the beginning (`pre_ixs`), in the middle (`ixs`) and at the end (`post_ixs`) of each fuzz iteration. This can be useful for example if your program needs an initialization or you want to fuzz some specific program state. Go to the bin target file of your fuzz test and implement the corresponding optional method of the `FuzzDataBuilder` trait. For example, in order to always call the `initialize` instruction for the default fuzz target, modify the trait's implementation in `trdelnik-tests/fuzz_tests//test_fuzz.rs` file as follows: ```rust impl FuzzDataBuilder for MyFuzzData { fn pre_ixs(u: &mut arbitrary::Unstructured) -> arbitrary::Result> { diff --git a/README.md b/README.md index 5a5c217b..1faa4df7 100644 --- a/README.md +++ b/README.md @@ -54,11 +54,11 @@ trdelnik fuzz run trdelnik --help ``` ### How to write fuzz tests? -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`. +Once you initialize Trdelnik in your Anchor project, you will find a fuzz test template in the `trdelnik-tests/fuzz_tests/fuzz_0` folder that you can modify according to your needs or create new targets. Do not forget to install honggfuzz-rs using `cargo install honggfuzz`. ```shell -# To run the fuzz test, execute this command from your terminal and replace with the name of your fuzz target (by default "fuzz_target") +# To run the fuzz test, execute this command from your terminal and replace with the name of particular fuzz test (for example: "fuzz_0") trdelnik fuzz run # To debug your fuzz target crash with parameters from a crash file @@ -84,8 +84,8 @@ Trdelnik also supports writing integration tests in Rust. ```rust -// /trdelnik-tests/tests/test.rs -// TODO: do not forget to add all necessary dependencies to the generated `trdelnik-tests/Cargo.toml` +// /trdelnik-tests/poc_tests/tests/test.rs +// TODO: do not forget to add all necessary dependencies to the generated `trdelnik-tests/poc_tests/Cargo.toml` use program_client::my_instruction; use trdelnik_client::*; use my_program; @@ -174,14 +174,14 @@ async fn test() {} - `Trdelnik` does not export `anchor-spl` and `spl-associated-token-account`, so you have to add it manually. ```toml -# /trdelnik-tests/Cargo.toml +# /trdelnik-tests/poc_tests/Cargo.toml # import the correct versions manually anchor-spl = "0.28.0" spl-associated-token-account = "2.0.0" ``` ```rust -// /trdelnik-tests/tests/test.rs +// /trdelnik-tests/poc_tests/tests/test.rs use anchor_spl::token::Token; use spl_associated_token_account; diff --git a/crates/cli/src/command/fuzz.rs b/crates/cli/src/command/fuzz.rs index a81d6927..794ffbe4 100644 --- a/crates/cli/src/command/fuzz.rs +++ b/crates/cli/src/command/fuzz.rs @@ -22,6 +22,7 @@ pub enum FuzzCommand { /// Path to the crash file crash_file_path: String, }, + /// Add new fuzz test. Explicit fuzz test name is not yet supported. Implicit name is fuzz_ID, where ID is automatically derived. Add, } diff --git a/crates/cli/src/lib.rs b/crates/cli/src/lib.rs index 4b21d49a..d07fee67 100644 --- a/crates/cli/src/lib.rs +++ b/crates/cli/src/lib.rs @@ -30,13 +30,13 @@ enum Command { #[clap(subcommand)] subcmd: KeyPairCommand, }, - /// Run program tests + /// Run program Integration tests Test { /// Anchor project root #[clap(short, long, default_value = "./")] root: String, }, - /// Run and debug fuzz tests + /// Run and debug Fuzz tests Fuzz { /// Anchor project root #[clap(short, long)]