fuzz.rs 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. use {
  2. solana_account_info::AccountInfo,
  3. solana_banks_client::BanksClient,
  4. solana_hash::Hash,
  5. solana_instruction::Instruction,
  6. solana_keypair::Keypair,
  7. solana_msg::msg,
  8. solana_program_error::ProgramResult,
  9. solana_program_test::{processor, ProgramTest},
  10. solana_pubkey::Pubkey,
  11. solana_rent::Rent,
  12. solana_signer::Signer,
  13. solana_system_interface::instruction as system_instruction,
  14. solana_transaction::Transaction,
  15. };
  16. fn process_instruction(
  17. _program_id: &Pubkey,
  18. _accounts: &[AccountInfo],
  19. _input: &[u8],
  20. ) -> ProgramResult {
  21. msg!("Processing instruction");
  22. Ok(())
  23. }
  24. #[test]
  25. fn simulate_fuzz() {
  26. let rt = tokio::runtime::Runtime::new().unwrap();
  27. let program_id = Pubkey::new_unique();
  28. // Initialize and start the test network
  29. let program_test = ProgramTest::new(
  30. "program-test-fuzz",
  31. program_id,
  32. processor!(process_instruction),
  33. );
  34. let (mut banks_client, payer, last_blockhash) = rt.block_on(program_test.start());
  35. // the honggfuzz `fuzz!` macro does not allow for async closures,
  36. // so we have to use the runtime directly to run async functions
  37. rt.block_on(run_fuzz_instructions(
  38. &[1, 2, 3, 4, 5],
  39. &mut banks_client,
  40. &payer,
  41. last_blockhash,
  42. &program_id,
  43. ));
  44. }
  45. #[test]
  46. fn simulate_fuzz_with_context() {
  47. let rt = tokio::runtime::Runtime::new().unwrap();
  48. let program_id = Pubkey::new_unique();
  49. // Initialize and start the test network
  50. let program_test = ProgramTest::new(
  51. "program-test-fuzz",
  52. program_id,
  53. processor!(process_instruction),
  54. );
  55. let mut context = rt.block_on(program_test.start_with_context());
  56. // the honggfuzz `fuzz!` macro does not allow for async closures,
  57. // so we have to use the runtime directly to run async functions
  58. rt.block_on(run_fuzz_instructions(
  59. &[1, 2, 3, 4, 5],
  60. &mut context.banks_client,
  61. &context.payer,
  62. context.last_blockhash,
  63. &program_id,
  64. ));
  65. }
  66. async fn run_fuzz_instructions(
  67. fuzz_instruction: &[u8],
  68. banks_client: &mut BanksClient,
  69. payer: &Keypair,
  70. last_blockhash: Hash,
  71. program_id: &Pubkey,
  72. ) {
  73. let mut instructions = vec![];
  74. let mut signer_keypairs = vec![];
  75. for &i in fuzz_instruction {
  76. let keypair = Keypair::new();
  77. let instruction = system_instruction::create_account(
  78. &payer.pubkey(),
  79. &keypair.pubkey(),
  80. Rent::default().minimum_balance(i as usize),
  81. i as u64,
  82. program_id,
  83. );
  84. instructions.push(instruction);
  85. instructions.push(Instruction::new_with_bincode(*program_id, &[0], vec![]));
  86. signer_keypairs.push(keypair);
  87. }
  88. // Process transaction on test network
  89. let mut transaction = Transaction::new_with_payer(&instructions, Some(&payer.pubkey()));
  90. let signers = [payer]
  91. .iter()
  92. .copied()
  93. .chain(signer_keypairs.iter())
  94. .collect::<Vec<&Keypair>>();
  95. transaction.partial_sign(&signers, last_blockhash);
  96. banks_client.process_transaction(transaction).await.unwrap();
  97. for keypair in signer_keypairs {
  98. let account = banks_client
  99. .get_account(keypair.pubkey())
  100. .await
  101. .expect("account exists")
  102. .unwrap();
  103. assert!(account.lamports > 0);
  104. assert!(!account.data.is_empty());
  105. }
  106. }