trident_template/
test_fuzz_generator.rs

1use quote::{format_ident, ToTokens};
2use syn::parse_quote;
3use trident_idl_spec::Idl;
4
5pub fn generate_source_code(_idl_instructions: &[Idl], lib_names: &[String]) -> String {
6    let mut use_statements: Vec<syn::ItemUse> = Vec::new();
7
8    let mut programs: Vec<syn::Stmt> = Vec::new();
9
10    let mut input_array: Vec<syn::Ident> = Vec::new();
11
12    for program in lib_names {
13        let (use_statement, program, program_variable) = process_program_entries(program);
14        // add to the use statements
15        use_statements.push(use_statement);
16        // add to the programs
17        programs.push(program);
18        // add to the input array
19        input_array.push(program_variable);
20    }
21
22    let test_fuzz_definition: syn::File = parse_quote! {
23        use trident_fuzz::fuzzing::*;
24        mod fuzz_instructions;
25        use fuzz_instructions::FuzzInstruction;
26        use fuzz_instructions::*;
27
28        #(#use_statements)*
29
30        struct InstructionsSequence;
31
32
33        /// Define instruction sequences for invocation.
34        /// `pre` runs at the start, `middle` in the middle, and `post` at the end.
35        /// For example, to call `InitializeFn`, `UpdateFn` and then `WithdrawFn` during each fuzzing iteration:
36        /// ```
37        /// impl FuzzDataBuilder<FuzzInstruction> for InstructionsSequence {
38        ///     pre_sequence!(InitializeFn,UpdateFn);
39        ///     middle_sequence!(WithdrawFn);
40        ///}
41        /// ```
42        /// For more details, see: https://ackee.xyz/trident/docs/latest/features/instructions-sequences/#instructions-sequences
43        impl FuzzDataBuilder<FuzzInstruction> for InstructionsSequence {}
44
45        fn main() {
46
47            #(#programs)*
48
49            let config = TridentConfig::new();
50            let mut client = TridentSVM::new_client(&[ #(#input_array),* ], &config);
51            fuzz_trident!(
52                fuzz_ix: FuzzInstruction,
53                |fuzz_data: InstructionsSequence, client: TridentSVM, config: TridentConfig|
54            );
55        }
56    };
57
58    test_fuzz_definition.into_token_stream().to_string()
59}
60
61fn process_program_entries(lib_name: &String) -> (syn::ItemUse, syn::Stmt, syn::Ident) {
62    // library name as identifier
63    let library = format_ident!("{}", lib_name);
64    // entry name as identifier
65    let library_entry = format_ident!("entry_{}", lib_name);
66    // variable name as identifier
67    let variable_name = format_ident!("program_{}", library);
68
69    // initial use statement
70    let use_statement = parse_quote!(use #library::entry as #library_entry;);
71
72    // program definition
73    let program = parse_quote! {
74        let #variable_name = ProgramEntrypoint::new(
75            pubkey!("fill corresponding program ID here"),
76            None,
77            processor!(#library_entry)
78        );
79    };
80
81    (use_statement, program, variable_name)
82}