| 
									
										
										
										
											2021-01-29 14:23:59 +01:00
										 |  |  | use {
 | 
					
						
							|  |  |  |     solana_banks_client::BanksClient,
 | 
					
						
							| 
									
										
										
										
											2021-04-02 08:54:09 -07:00
										 |  |  |     solana_program_test::{processor, ProgramTest},
 | 
					
						
							|  |  |  |     solana_sdk::{
 | 
					
						
							| 
									
										
										
										
											2021-12-03 09:00:31 -08:00
										 |  |  |         account_info::AccountInfo,
 | 
					
						
							|  |  |  |         entrypoint::ProgramResult,
 | 
					
						
							|  |  |  |         hash::Hash,
 | 
					
						
							|  |  |  |         instruction::Instruction,
 | 
					
						
							|  |  |  |         msg,
 | 
					
						
							|  |  |  |         pubkey::Pubkey,
 | 
					
						
							|  |  |  |         rent::Rent,
 | 
					
						
							|  |  |  |         signature::{Keypair, Signer},
 | 
					
						
							|  |  |  |         system_instruction,
 | 
					
						
							| 
									
										
										
										
											2021-04-02 08:54:09 -07:00
										 |  |  |         transaction::Transaction,
 | 
					
						
							| 
									
										
										
										
											2021-01-29 14:23:59 +01:00
										 |  |  |     },
 | 
					
						
							|  |  |  | };
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #[allow(clippy::unnecessary_wraps)]
 | 
					
						
							|  |  |  | fn process_instruction(
 | 
					
						
							|  |  |  |     _program_id: &Pubkey,
 | 
					
						
							|  |  |  |     _accounts: &[AccountInfo],
 | 
					
						
							|  |  |  |     _input: &[u8],
 | 
					
						
							|  |  |  | ) -> ProgramResult {
 | 
					
						
							| 
									
										
										
										
											2021-02-03 13:45:29 +01:00
										 |  |  |     msg!("Processing instruction");
 | 
					
						
							| 
									
										
										
										
											2021-01-29 14:23:59 +01:00
										 |  |  |     Ok(())
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #[test]
 | 
					
						
							|  |  |  | fn simulate_fuzz() {
 | 
					
						
							|  |  |  |     let rt = tokio::runtime::Runtime::new().unwrap();
 | 
					
						
							|  |  |  |     let program_id = Pubkey::new_unique();
 | 
					
						
							|  |  |  |     // Initialize and start the test network
 | 
					
						
							|  |  |  |     let program_test = ProgramTest::new(
 | 
					
						
							|  |  |  |         "program-test-fuzz",
 | 
					
						
							|  |  |  |         program_id,
 | 
					
						
							|  |  |  |         processor!(process_instruction),
 | 
					
						
							|  |  |  |     );
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     let (mut banks_client, payer, last_blockhash) =
 | 
					
						
							|  |  |  |         rt.block_on(async { program_test.start().await });
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // the honggfuzz `fuzz!` macro does not allow for async closures,
 | 
					
						
							|  |  |  |     // so we have to use the runtime directly to run async functions
 | 
					
						
							|  |  |  |     rt.block_on(async {
 | 
					
						
							|  |  |  |         run_fuzz_instructions(
 | 
					
						
							|  |  |  |             &[1, 2, 3, 4, 5],
 | 
					
						
							|  |  |  |             &mut banks_client,
 | 
					
						
							|  |  |  |             &payer,
 | 
					
						
							|  |  |  |             last_blockhash,
 | 
					
						
							|  |  |  |             &program_id,
 | 
					
						
							|  |  |  |         )
 | 
					
						
							|  |  |  |         .await
 | 
					
						
							|  |  |  |     });
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #[test]
 | 
					
						
							|  |  |  | fn simulate_fuzz_with_context() {
 | 
					
						
							|  |  |  |     let rt = tokio::runtime::Runtime::new().unwrap();
 | 
					
						
							|  |  |  |     let program_id = Pubkey::new_unique();
 | 
					
						
							|  |  |  |     // Initialize and start the test network
 | 
					
						
							|  |  |  |     let program_test = ProgramTest::new(
 | 
					
						
							|  |  |  |         "program-test-fuzz",
 | 
					
						
							|  |  |  |         program_id,
 | 
					
						
							|  |  |  |         processor!(process_instruction),
 | 
					
						
							|  |  |  |     );
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-02 08:54:09 -07:00
										 |  |  |     let mut context = rt.block_on(async { program_test.start_with_context().await });
 | 
					
						
							| 
									
										
										
										
											2021-01-29 14:23:59 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // the honggfuzz `fuzz!` macro does not allow for async closures,
 | 
					
						
							|  |  |  |     // so we have to use the runtime directly to run async functions
 | 
					
						
							|  |  |  |     rt.block_on(async {
 | 
					
						
							|  |  |  |         run_fuzz_instructions(
 | 
					
						
							|  |  |  |             &[1, 2, 3, 4, 5],
 | 
					
						
							| 
									
										
										
										
											2021-04-02 08:54:09 -07:00
										 |  |  |             &mut context.banks_client,
 | 
					
						
							|  |  |  |             &context.payer,
 | 
					
						
							|  |  |  |             context.last_blockhash,
 | 
					
						
							| 
									
										
										
										
											2021-01-29 14:23:59 +01:00
										 |  |  |             &program_id,
 | 
					
						
							|  |  |  |         )
 | 
					
						
							|  |  |  |         .await
 | 
					
						
							|  |  |  |     });
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | async fn run_fuzz_instructions(
 | 
					
						
							|  |  |  |     fuzz_instruction: &[u8],
 | 
					
						
							|  |  |  |     banks_client: &mut BanksClient,
 | 
					
						
							|  |  |  |     payer: &Keypair,
 | 
					
						
							|  |  |  |     last_blockhash: Hash,
 | 
					
						
							|  |  |  |     program_id: &Pubkey,
 | 
					
						
							|  |  |  | ) {
 | 
					
						
							|  |  |  |     let mut instructions = vec![];
 | 
					
						
							|  |  |  |     let mut signer_keypairs = vec![];
 | 
					
						
							|  |  |  |     for &i in fuzz_instruction {
 | 
					
						
							|  |  |  |         let keypair = Keypair::new();
 | 
					
						
							|  |  |  |         let instruction = system_instruction::create_account(
 | 
					
						
							|  |  |  |             &payer.pubkey(),
 | 
					
						
							|  |  |  |             &keypair.pubkey(),
 | 
					
						
							|  |  |  |             Rent::default().minimum_balance(i as usize),
 | 
					
						
							|  |  |  |             i as u64,
 | 
					
						
							|  |  |  |             program_id,
 | 
					
						
							|  |  |  |         );
 | 
					
						
							|  |  |  |         instructions.push(instruction);
 | 
					
						
							| 
									
										
										
										
											2021-03-03 21:46:48 -08:00
										 |  |  |         instructions.push(Instruction::new_with_bincode(*program_id, &[0], vec![]));
 | 
					
						
							| 
									
										
										
										
											2021-01-29 14:23:59 +01:00
										 |  |  |         signer_keypairs.push(keypair);
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  |     // Process transaction on test network
 | 
					
						
							|  |  |  |     let mut transaction = Transaction::new_with_payer(&instructions, Some(&payer.pubkey()));
 | 
					
						
							|  |  |  |     let signers = [payer]
 | 
					
						
							|  |  |  |         .iter()
 | 
					
						
							|  |  |  |         .copied()
 | 
					
						
							|  |  |  |         .chain(signer_keypairs.iter())
 | 
					
						
							|  |  |  |         .collect::<Vec<&Keypair>>();
 | 
					
						
							|  |  |  |     transaction.partial_sign(&signers, last_blockhash);
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     banks_client.process_transaction(transaction).await.unwrap();
 | 
					
						
							|  |  |  |     for keypair in signer_keypairs {
 | 
					
						
							|  |  |  |         let account = banks_client
 | 
					
						
							|  |  |  |             .get_account(keypair.pubkey())
 | 
					
						
							|  |  |  |             .await
 | 
					
						
							|  |  |  |             .expect("account exists")
 | 
					
						
							|  |  |  |             .unwrap();
 | 
					
						
							|  |  |  |         assert!(account.lamports > 0);
 | 
					
						
							|  |  |  |         assert!(!account.data.is_empty());
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  | }
 |